Hello I want to create Serialization class to serialize my variables settings to file or buffer. I was doing good until I start to implement std::variant<T...> in my Class. As far as I understand. I can not get variant types in runtime. It need to be completed in compile time. But I want to store in file. So here is my code.
class Serialization
{
private:
std::vector<char> buffer;
public:
inline std::size_t size()const{return buffer.size();};
Serialization()=default;
template<typename T>
Serialization& operator<<(const T& val){
static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable");
const auto size = buffer.size();
buffer.resize(buffer.size()+sizeof(T));
std::memcpy(buffer.data() + size, static_cast<const void*>(&val), sizeof(T));
return *this;
}
template<typename T>
Serialization& operator>>(T& val){
static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable");
std::memcpy(&val, buffer.data(), sizeof(T));
buffer.erase(buffer.begin(), buffer.begin() + sizeof(T));
return *this;
}
template<typename T>
Serialization& operator<<(const std::vector<T>& val) {
const auto size = val.size();
*this << size;
for(const auto& elem : val){
*this << elem;
}
return *this;
}
template<typename T>
Serialization& operator>>(std::vector<T>& val) {
size_t size;
*this >> size;
val.resize(size);
for(auto& elem : val){
*this >> elem;
}
return *this;
}
template< class... Types >
Serialization& operator<<(const std::variant<Types...>& val) {
const std::size_t index = val.index();
*this << index;
std::visit([&](const auto& value){
*this << value;
}, val);
return *this;
}
template< class... Types >
Serialization& operator>>(std::variant<Types...>& val) {
std::size_t index;
*this >> index;
if (index >= sizeof...(Types)) {
throw std::out_of_range("Variant index out of range");
}
using value_type = std::variant_alternative_t<index, std::variant<Types...>>;
//auto value = expand_type<Types...>(index);
value_type value;
*this >> value;
val.emplace<index>(std::move(value));
return *this;
}
//I also try this one
template <typename... Ts>
[[nodiscard]] std::variant<Ts...>
expand_type(std::size_t i)
{
assert(i < sizeof...(Ts));
static constexpr std::variant<Ts...> table[] = { Ts{ }... };
return table[i];
}
friend std::ostream & operator << (std::ostream &out, const Serialization &s);
friend std::istream & operator >> (std::istream &in, Serialization &s);
~Serialization()=default;
};
template<>
Serialization& Serialization::operator<<(const std::string& val){
const auto size = val.size();
*this << size;
buffer.insert(buffer.end(), val.begin(), val.end());
return *this;
}
template<>
Serialization& Serialization::operator>>(std::string& val) {
size_t size;
*this >> size;
val.resize(size);
std::memcpy(&val[0], buffer.data(), size);
buffer.erase(buffer.begin(), buffer.begin() +size);
return *this;
}
std::ostream & operator << (std::ostream &out, const Serialization &s){
out.write(s.buffer.data(),s.buffer.size());
return out;
}
std::istream & operator >> (std::istream &in, Serialization &s){
in.seekg(0, std::ios::end);
s.buffer.resize(in.tellg());
in.seekg(0, std::ios::beg);
in.read(s.buffer.data(), s.buffer.size());
return in;
}
I check forums blogs and documentation. I also ask ChatGPT. I couldn't find to way to implement this.