从 boost 序列化档案中构造对象
Posted
技术标签:
【中文标题】从 boost 序列化档案中构造对象【英文标题】:Construct object from boost serialization archive 【发布时间】:2012-03-06 18:26:31 【问题描述】:是否可以直接从存档中构造对象?
这样的……
// Non-working pseudo code
struct Foo
BOOST_SERIALIZATION_SPLIT_MEMBER();
std::vector<int> data;
Foo()
// populate "data" by doing calculation
data.push_back(1); data.push_back(2);
template<class Archive>
Foo( Archive & ar )
// populate "data" by rading the archive
template<class Archive>
void save(Archive & ar, const unsigned int version) const
// Normal serialization of data
ar << data;
;
int main(int argc, const char *argv[])
// deserialize
boost::archive::text_iarchive oar(std::cin);
Foo foo(oar);
return 0;
【问题讨论】:
是的,为什么不呢?只需添加“ar >> data;”在构造函数中,你就完成了。 (真正的挑战是“数据”是否为常量) @alfC 如果 'data' 没有默认构造函数,你会怎么做? @DavidDoria,正如 Alexander Stepanov 所说,“如果你不让你的类默认可构造,那么你就会得到你应得的”。所有类都应该有一个默认构造函数,如果没有(并且您无法控制它),您必须在Foo( Archive & ar ) : data(something)
级别解决此问题,或者具有Foot(Archive & ar) : data(somefunction(ar))
的间接级别(但有些东西在第一名)。
@alfC 默认构造函数有什么好处?它只会增加您的对象可能处于的状态数量(其中大部分是您必须注意的不良/无效状态),不是吗?
@DavidDoria,您将默认构造函数与未初始化的变量混淆了。默认构造函数应该让您的对象处于有效状态(如果可能的话,也是可预测的状态)。
【参考方案1】:
您可以使用反序列化构造函数:
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <fstream>
class Point
public:
Point() = default;
Point(boost::archive::text_iarchive& archive)
archive >> *this;
float x = 1.;
float y = 2.;
private:
friend class boost::serialization::access;
template<class TArchive>
void serialize(TArchive & archive, const unsigned int version)
archive & x;
archive & y;
;
int main()
Point p;
p.x = 5;
p.y = 6;
std::ofstream outputStream("test.archive");
boost::archive::text_oarchive outputArchive(outputStream);
outputArchive << p;
outputStream.close();
std::ifstream inputStream("test.archive");
boost::archive::text_iarchive inputArchive(inputStream);
Point pointRead(inputArchive);
std::cout << pointRead.x << " " << pointRead.y << std::endl;
return 0;
【讨论】:
【参考方案2】:正如我在评论中所说。
是的,从档案中构建没有问题。
(另一种选择是使用static load
函数,但这可能会导致性能下降)。
我看到你的方法的唯一潜在问题是你的构造函数几乎可以接受任何东西作为参数,这可能会产生问题。 这可能会干扰依赖于隐式转换的复制构造函数和其他单参数构造函数。
所以必须限制只能获取档案。
有不同的方法可以做到这一点,但基于此对话http://marc.info/?l=boost&m=121131260728308&w=2,并且archives
的继承树 记录了http://www.boost.org/doc/libs/1_35_0/libs/serialization/doc/class_diagram.html,我认为这是最好的解决方案是检查参数是否来自basic_iarchive
。
#include<type_traits>
struct Foo
...
std::vector<int> data;
Foo()
// populate "data" by doing calculation
data.push_back(1); data.push_back(2);
template<class IArchive,
typename = std::enable_if_t<std::is_base_of<boost::archive::detail::basic_iarchive, IArchive>::value>>
Foo( IArchive & ar )
ar >> data;
// populate "data" by reading the archive
...
;
int main(int argc, const char *argv[])
// deserialize
boost::archive::text_iarchive iar(std::cin);
Foo foo(iar); // will also work with other archives
至于当您的数据不是默认构造时会发生什么,请参阅上面的讨论。
【讨论】:
以上是关于从 boost 序列化档案中构造对象的主要内容,如果未能解决你的问题,请参考以下文章