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

vs3odd8k  于 2023-06-07  发布在  Hive
关注(0)|答案(2)|浏览(274)

我有以下枚举

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

一个stringstream:

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

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

ar << Example::First;

boost串行化4个字节(在本例中为0x01、0x00、0x00、0x00)位,而不是uint8_t所需的8位(0x01)。有什么办法可以避免这种情况吗?我的意思是,我知道我可以将枚举转换为uint8_t,但这似乎不是很聪明(如果我必须这样做,我必须改变很多事情)。
感谢和问候

bvjxkvbb

bvjxkvbb1#

与Boost序列化一样,要自定义用户定义类型的处理,您需要实现 * 定制点 *,它是成员serialize/load/save或自由函数serialize/load/save(由ADL查找)。
由于成员函数不是枚举的选项,因此需要为类型提供重载,例如serialize。可悲的是,没有办法让它的泛型实现比内置基元类型的预定义重载“更好”。
以下是接近的(但它不起作用¹):

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));
            }

} }

我们可以采用“binary_object”序列化的捷径,因为我们通过定义知道枚举具有整数值作为其底层类型,这使它们成为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 Package 器,它将透明地处理序列化和反序列化。
请参阅Boost文档中的Boost序列化 Package 器
¹由于类似的原因,BOOST_IS_BITWISE_SERIALIZABLE(Example)将无法工作;我测试过了

6mw9ycah

6mw9ycah2#

我认为自然的答案是将枚举转换为枚举的底层类型,并对其进行(反)序列化。
至少,这会给予一个更易读的输出;在最好的情况下,它将创建跨系统的更兼容的存档。
还要注意binary序列化可能会破坏xml的(我认为这是Boost.Serialization中的一个bug)

using boost::serialization::make_binary_object;

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

int main() {

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

    auto data = Example::First;
    auto data_ul = static_cast<uint8_t>(data);

    ar << boost::make_nvp("data", data_ul);
    
    ar << boost::make_nvp("data_bin", make_binary_object(&data, sizeof(data)));

    ar << make_binary_object(&data, sizeof(data));

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

http://coliru.stacked-crooked.com/a/c824a88d139d07cf
输出:

Size: <data>1</data>

<data_bin>

AQ==

</data_bin>

AQ==

相关问题