Skip to content

Instantly share code, notes, and snippets.

@mashoujiang
Last active October 5, 2022 15:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mashoujiang/0eb3aed7273d0ac0fee2d3f93eb1cb10 to your computer and use it in GitHub Desktop.
Save mashoujiang/0eb3aed7273d0ac0fee2d3f93eb1cb10 to your computer and use it in GitHub Desktop.
One interesting C++ template programming case

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;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment