2
\$\begingroup\$

I am experimenting with asio web sockets and tried to write a simple serializer / deserializer.

I am also thinking about an approach on how to serialize some type information alongside the actual data. This way a dont have to worry about that i might choose the wrong type when deserializing.

// serialize.hpp

template<typename T>
struct serialize {
  static_assert(std::is_fundamental_v<T> || std::is_standard_layout_v<T>, "Only primitives and PODs can be serialized");

  std::array<std::byte, sizeof(T)> operator()(const T& object) {
    auto buffer = std::array<std::byte, sizeof(T)>{};

    const auto begin = static_cast<const std::byte*>(static_cast<const void*>(std::addressof(object)));

    std::copy_n(begin, sizeof(T), buffer.begin());

    return buffer;
  }
};

// deserialize.hpp

template<typename T>
struct deserialize {
  static_assert(std::is_fundamental_v<T> || std::is_standard_layout_v<T>, "Only primitives and PODs can be serialized");

  T operator()(const std::array<std::byte, sizeof(T)>& buffer) {
    T object;

    const auto begin = static_cast<std::byte*>(static_cast<void*>(std::addressof(object)));

    std::copy_n(buffer.begin(), sizeof(T), begin);

    return object;
  }
};
\$\endgroup\$
1

1 Answer 1

2
\$\begingroup\$

std::is_standard_layout

std::is_standard_layout_v<T> == true does not imply that an object is a POD-type. An object is a POD-type if it is both std::is_standard_layout_v<T> && std::is_trivial_v<T>. Here's an excellent summary.


std::is_pod_v

If you're using C++17, or an older standard, you can use std::is_pod_v<T> to determine if a type is a POD-type.


No need for std::is_fundamental_v

A fundamental type is guaranteed to be a POD-type.


Use std::is_trivially_copyable_v

There are types which are memcpy-able but not POD-types. For example,

struct NonPODButMemcpyableType
{
    int x = 42;
}

The existence of the default value disqualifies it from being a POD-type. It will raise a compile error, but it should still be (de)serializable. You should std::is_trivially_copyable_v<T> instead.


The cast to const void* can be avoided if you use reinterpret_cast<std::byte*>. It is legal in this case, since you're casting to a char type.


\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.