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 T
adalah tipe yang ingin Anda serialisasi Mode
adalah tipe dummy untuk membedakan antara berbagai jenis serialisasi, mis. integer yang sama dapat diserialkan sebagai little endian, big endian, varint, dll.
Secara default, Serializer
mendelegasikan 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.