如何一个boost ::档案:: binary_oarchive处理枚举? [英] How does a boost::archive::binary_oarchive handle an enum?
问题描述
我有以下的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 functionserialize/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:#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 insideserialize
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屋!