Saya menggunakan template berikut untuk mengimplementasikan serialisasi:
template <class T, class Mode = void> struct Serializer
{
template <class OutputCharIterator>
static void serializeImpl(const T &object, OutputCharIterator &&it)
{
object.template serializeThis<Mode>(it);
}
template <class InputCharIterator>
static T deserializeImpl(InputCharIterator &&it, InputCharIterator &&end)
{
return T::template deserializeFrom<Mode>(it, end);
}
};
template <class Mode = void, class T, class OutputCharIterator>
void serialize(const T &object, OutputCharIterator &&it)
{
Serializer<T, Mode>::serializeImpl(object, it);
}
template <class T, class Mode = void, class InputCharIterator>
T deserialize(InputCharIterator &&it, InputCharIterator &&end)
{
return Serializer<T, Mode>::deserializeImpl(it, end);
}
template <class Mode = void, class T, class InputCharIterator>
void deserialize(T &result, InputCharIterator &&it, InputCharIterator &&end)
{
result = Serializer<T, Mode>::deserializeImpl(it, end);
}
Berikut Tadalah tipe yang ingin Anda serialisasi Modeadalah tipe dummy untuk membedakan antara berbagai jenis serialisasi, mis. integer yang sama dapat diserialkan sebagai little endian, big endian, varint, dll.
Secara default, Serializermendelegasikan tugas ke objek yang diserialisasi. Untuk tipe bawaan, Anda harus membuat spesialisasi template dari Serializer.
Templat fungsi kenyamanan juga disediakan.
Misalnya serialisasi little endian dari unsigned integers:
struct LittleEndianMode
{
};
template <class T>
struct Serializer<
T, std::enable_if_t<std::is_unsigned<T>::value, LittleEndianMode>>
{
template <class InputCharIterator>
static T deserializeImpl(InputCharIterator &&it, InputCharIterator &&end)
{
T res = 0;
for (size_t i = 0; i < sizeof(T); i++)
{
if (it == end) break;
res |= static_cast<T>(*it) << (CHAR_BIT * i);
it++;
}
return res;
}
template <class OutputCharIterator>
static void serializeImpl(T number, OutputCharIterator &&it)
{
for (size_t i = 0; i < sizeof(T); i++)
{
*it = (number >> (CHAR_BIT * i)) & 0xFF;
it++;
}
}
};
Kemudian untuk membuat serial:
std::vector<char> serialized;
uint32_t val = 42;
serialize<LittleEndianMode>(val, std::back_inserter(serialized));
Untuk deserialisasi:
uint32_t val;
deserialize(val, serialized.begin(), serialized.end());
Karena logika iterator abstrak, ia harus bekerja dengan iterator apa pun (misalnya, iterator aliran), penunjuk, dll.