boost::archive::binary_oarchive 如何处理枚举?

How does a boost::archive::binary_oarchive handle an enum?

我有以下枚举

enum Example : uint8_t {
   First = 1,
   Second = 2,
 };

和一个字符串流:

std::stringstream stream;
boost::archive::binary_oarchive ar(stream);

现在我注意到,如果我序列化一个枚举:

ar << Example::First;

boost 序列化 4 字节(在本例中为 0x01、0x00、0x00、0x00)位,而不是 uint8_t 所需的 8 位 (0x01)。 有什么办法可以避免这种情况吗?我的意思是,我知道我可以将该枚举转换为 uint8_t,但这种接缝不是很智能(如果必须这样做,我必须更改很多东西)。

谢谢和问候

与 Boost Serialization 一样,要自定义用户定义类型的处理,您需要实现 自定义点,它是成员 serialize/load/save 或免费的函数 serialize/load/save(由 ADL 查找)。

由于成员函数不是枚举的选项,因此您需要为您的类型提供重载,例如 serialize。可悲的是,除了内置基本类型的预定义重载之外,没有办法获得 "better" 的通用实现。

这是接近的结果(但它不起作用¹):

namespace boost { namespace serialization {

        template <typename Ar, typename T>
            typename std::enable_if<std::is_enum<T>::value, void>::type
            serialize(Ar& ar, T& e, unsigned) 
            {
                ar & boost::serialization::make_binary_object(&e, sizeof(e));
            }

} }

We can take the shortcut of "binary_object" serialization as we know by definition that enums have integral values as their underlying type, which makes them POD.

鉴于这个——不幸的——限制,也许最好的方法是手动调用 make_binary_object,如下所示:

Live On Coliru

#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/binary_object.hpp>
#include <boost/serialization/serialization.hpp>
#include <iostream>
#include <sstream>

using boost::serialization::make_binary_object;

enum class Example : uint8_t {
    First  = 1,
    Second = 2,
};

int main() {

    std::stringstream stream;
    boost::archive::binary_oarchive ar(stream, boost::archive::no_header);

    auto data = Example::First;
    ar << make_binary_object(&data, sizeof(data));

    std::cout << "Size: " << stream.str().size() << "\n";
}

打印

Size: 1

符合预期。您可以在 serialize 实现中使用 make_binary_object 包装器,它将透明地处理序列化和反序列化。

请参阅:Boost Serialization Wrappers Boost 文档


¹ 出于类似原因,BOOST_IS_BITWISE_SERIALIZABLE(Example) 将不起作用;我测试了