我有一个向量,其中包含带有boost :: variant元素的结构。
现在我必须序列化这个载体。由于规范,我必须计算保存此向量所需的八位字节。现在,我正在寻找一种方法来轻松实现这一目标。
int allSize = 0;
for(auto it=vec.begin(); it != vec.end(); it++){
//something like size = sizeof(it->variant)
allsize += size;
}
我试图用
来获取元素的大小sizeof(it->variant.type())
但这仅显示变量元素的大小(这是te变体中保存的最大元素的大小)
那么,是否有一种简单的方法来获得序列化数据的大小? 或者我是否必须使用大约7个模板来编写访问者?
答案 0 :(得分:2)
您可以在访问者中执行此操作,如下所示:
/*
template <typename T>
using EnableIf = typename std::enable_if< std::is_pod<T>::value >::type* ;
*/
struct visit: public boost::static_visitor<>
{
visit( ): size(0) { }
template<typename T /*, EnableIf<T> = nullptr */ >
void operator()( T& x) const
{
size += sizeof ( x ) ;
//std::cout << sizeof ( x ) << ":" << x << '\n';
}
std::size_t get_size() const
{ return size ; }
private:
mutable std::size_t size ;
};
然后,
visit visito ;
std::for_each( vec.begin(), vec.end(),
boost::apply_visitor( visito) );
std::cout << visito.get_size() ;
编辑:删除评论以仅检查sehe评论的POD数据类型,因为保存非pod 所需的字节数可能并不总是等于sizeof(T)
答案 1 :(得分:1)
除了其他答案,你可以
size_t
使用稍微更通用的访问者对输出迭代器进行实际序列化:
struct serializer : public boost::static_visitor<> {
template<typename T, typename Out>
void operator()(T const& x, Out& out) const {
static_assert(boost::is_pod<T>(), "");
char const* rawp = reinterpret_cast<char const*>(&x);
std::copy(rawp, rawp+sizeof(T), out);
}
};
现在,您可以创建一个serialize
函数,该函数可以采用任何变体(实际上是可访问类型):
template <typename Variant, typename Out>
Out serialize(Variant const& v, Out into)
{
boost::apply_visitor(boost::bind(serializer(), _1, boost::ref(into)), v);
return into;
}
如果您不想序列化(但?)但只是想知道大小,可以传递函数输出迭代器而不是传统的输出迭代器:
template <typename Variant>
size_t serialized_size(Variant const& v) {
size_t octets = 0;
serialize(v, boost::make_function_output_iterator([&octets](char) { ++octets; }));
return octets;
}
#include <boost/array.hpp> // just as a sample
int main() {
typedef boost::variant<int, double, boost::array<char, 42> > V;
std::cout << "With int: " << serialized_size(V(0)) << "\n";
std::cout << "With double: " << serialized_size(V(3.14)) << "\n";
std::cout << "With array: " << serialized_size(V(boost::array<char,42>())) << "\n";
}
打印
With int: 4
With double: 8
With array: 42
为何如此通用?以上可以适用于非POD类型并支持您的用例(“我需要序列化它”);
请在此处查看序列化包含非POD和用户定义类型的变体的矢量: Live On Coliru
注意:
这些留给读者练习。