When reading binlog, I found one interesting code like below, just keep in mind here
#include < type_traits>
#include < cstdint>
#include < iostream>
struct Base {
int32_t i_data {123 };
uint64_t u_data {123 };
double d_data {123.0 };
};
template <typename T, typename Field>
auto serializable_member (Field T::*field) -> decltype(field);
template <typename T, typename ... Members>
struct StructSerializer {
template <typename Field, typename OutputStream>
static void serialize_member (const T& t, Field T::*field, OutputStream& ostream)
{
}
template <typename Field>
static std::size_t serialized_size_member (const T& t, Field T::*field)
{
return sizeof (t.*field);
}
static std::size_t serialized_size (const T &t) {
const std::size_t field_sizes[] = {0 , serialized_size_member (t, Members::value)...};
std::size_t result = 0 ;
for (auto s : field_sizes) { result += s; }
return result;
}
};
template <typename T, typename = void >
struct CustomSerializer
{
CustomSerializer () = delete ; // used by is_serializable
};
template <>
struct CustomSerializer <Base, void >
: StructSerializer<Base,
std::integral_constant<decltype(serializable_member(&Base::i_data)), &Base::i_data>,
std::integral_constant<decltype(serializable_member(&Base::u_data)), &Base::u_data>,
std::integral_constant<decltype(serializable_member(&Base::d_data)), &Base::d_data>> {
};
int32_t main (int32_t argc, char **argv) {
Base base;
size_t size = CustomSerializer<Base, void >::serialized_size (base);
std::cout << size << std::endl;
return 0 ;
}