如何一个boost ::档案:: binary_oarchive处理枚举? [英] How does a boost::archive::binary_oarchive handle an enum?

查看:317
本文介绍了如何一个boost ::档案:: binary_oarchive处理枚举?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下的Enum

 枚举示例:uint8_t有{
   第一= 1,
   第二= 2,
 };

和一个字符串流:

 的std :: stringstream的流;
提高::档案:: binary_oarchive AR(流);

现在我已经注意到了,如果我序列化枚举:

  AR<<例如::第一;

升压序列化4字节(在此情况下为0x01,0x00时,0×00,×00),而不是所需要的8位(0×01),用于一个uint8_t有位。
有什么办法避免这种情况?我的意思是,我知道我能投该枚举到uint8_t有但这接缝不是很聪明(我不得不改变很多东西,如果我必须这样做)。

感谢和问候


解决方案

由于总是与升压序列化,定制用户定义类型的治疗你需要实现的自定义对焦点的是无论是会员序列化/负载/保存或无功能连载/加载/保存(抬头通过ADL)。

由于成员函数是不是枚举一个选项,你需要提供过载,例如,连载你的类型。可悲的是有没有办法让一个通用的实施,要更好比predefined重载内建的基本类型。

下面就是会很接近(但它不工作¹):

 空间boost {空间序列{        模板< typename的氩气,typename的T>
            类型名称的std :: enable_if<的std :: is_enum< T> ::值,无效> ::类型
            序列化(AR&放大器; AR,T急症,无符号)
            {
                AR&安培;提高::系列化:: make_binary_object(急症室,的sizeof(E));
            }}}


  

我们可以采取binary_object序列化的快捷方式,因为我们知道通过定义,枚举有积分值作为其基础类型,这使得它们POD。


在此之光 - 不幸的 - 的限制,也许是最好的办法是手动调用 make_binary_object 如下所示:

<大骨节病> 住在Coliru

 的#include&LT;升压/存档/ binary_oarchive.hpp&GT;
#包括LT&;升压/存档/ binary_iarchive.hpp&GT;
#包括LT&;升压/系列化/ binary_object.hpp&GT;
#包括LT&;升压/系列化/ serialization.hpp&GT;
#包括LT&;&iostream的GT;
#包括LT&;&sstream GT;使用boost ::系列化:: make_binary_object;枚举类示例:uint8_t有{
    第一= 1,
    第二= 2,
};诠释主(){    的std :: stringstream的流;
    提高::档案:: binary_oarchive AR(流,提振::档案:: no_header);    自动数据=实例::第一;
    AR&LT;&LT; make_binary_object(安培;数据的sizeof(数据));    性病::法院LT&;&LT; 大小:&LT;&LT; stream.str()尺寸()&LT;&LT; \\ n;
}

它打印

 尺寸:1

预期。您可以使用 make_binary_object 包装在连载的实现,它会透明地照顾序列化和反序列化。

请参阅: 升压的序列化包装 Boost的文档


¹出于同样的原因, BOOST_IS_BITWISE_SERIALIZABLE(例)将无法正常工作;我测试了它

I have the following Enum

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

and a stringstream:

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

now i have noticed that, if i serialize an enum:

ar << Example::First;

boost serializes 4 byte (in this case 0x01, 0x00, 0x00, 0x00) bit instead of the needed 8 bit (0x01) for an uint8_t. Is there any way to avoid this? I mean, I know I can cast that enum to an uint8_t but this seams not very smart (and I have to change a lot of things if I have to do this).

Thanks and Greetings

解决方案

As always with Boost Serialization, to customize the treatment of user-defined types you'd need to implement the customization point which is either member serialize/load/save or free function serialize/load/save (looked up by ADL).

Since member functions are not an option for enums, you'd need to supply an overload of, e.g., serialize for your type. Sadly there is no way to get a generic implementation of that to be "better" than the predefined overloads for builtin primitive types.

Here's what would comes close (but it doesn't work ¹):

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.

In the light of this - unfortunate - limitation, perhaps the best way is to manually call make_binary_object as shown:

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

Which prints

Size: 1

as expected. You can use the make_binary_object wrapper inside serialize implementations and it will transparently take care of both serialization and deserialization.

See: Boost Serialization Wrappers in the Boost documentation


¹ for similar reasons, BOOST_IS_BITWISE_SERIALIZABLE(Example) will not work; I tested it

这篇关于如何一个boost ::档案:: binary_oarchive处理枚举?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆