C++ 从boost序列化存档中构造对象

C++ 从boost序列化存档中构造对象,c++,boost,boost-serialization,C++,Boost,Boost Serialization,是否可以直接从存档构建对象 像这样的 // 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); }

是否可以直接从存档构建对象

像这样的

// 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;
}
//非工作伪代码
结构Foo{
BOOST_SERIALIZATION_SPLIT_MEMBER();
std::矢量数据;
Foo(){
//通过计算填充“数据”
数据回推(1);数据回推(2);
}
模板
财务主任(档案及应收账款){
//通过调整归档文件的半径来填充“数据”
}
模板
无效保存(存档和应收账款,常量未签名整数版本)常量{
//数据的正常序列化

ar您可以使用反序列化构造函数:

#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;
}
#包括
#包括
#包括
类点
{
公众:
点()=默认值;
要点(boost::archive::text\u iarchive和archive)
{
存档>>*此文件;
}
浮动x=1。;
浮动y=2。;
私人:
好友类boost::serialization::access;
模板
void序列化(TArchive和archive,const unsigned int版本)
{
存档&x;
档案与y;
}
};
int main()
{
p点;
p、 x=5;
p、 y=6;
std::of流输出流(“test.archive”);
boost::archive::text\u oarchive outputArchive(outputStream);

outputArchive您可以使用反序列化构造函数

#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;
}
#包括
#包括
#包括
类点
{
公众:
点()=默认值;
要点(boost::archive::text\u iarchive和archive)
{
存档>>*此文件;
}
浮动x=1。;
浮动y=2。;
私人:
好友类boost::serialization::access;
模板
void序列化(TArchive和archive,const unsigned int版本)
{
存档&x;
档案与y;
}
};
int main()
{
p点;
p、 x=5;
p、 y=6;
std::of流输出流(“test.archive”);
boost::archive::text\u oarchive outputArchive(outputStream);
正如我在评论中所说,outputArchive。
是的,从存档中构建没有问题。
(另一种选择是使用
静态加载
功能,但可能会造成性能损失)

我看到您的方法唯一的潜在问题是,您的构造函数几乎可以将任何东西作为参数,这可能会产生问题。 这可能会干扰复制构造函数和其他依赖隐式转换的单参数构造函数

因此,我们必须限制只获取档案

有不同的方法可以做到这一点,但在本次对话中,由于
存档
的继承树已被记录在案,我认为最好的解决方案是检查参数是否来自
basic\u 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
}
#包括
结构Foo{
...
std::矢量数据;
Foo(){
//通过计算填充“数据”
数据回推(1);数据回推(2);
}
模板
Foo(Irchive&ar){
ar>>数据;
//通过读取归档来填充“数据”
}
...    
};
int main(int argc,const char*argv[]
{
//反序列化
boost::archive::text\u iarchive iar(std::cin);
Foo-Foo(iar);//还将与其他档案一起使用
}
至于当您的数据不是默认值时会发生什么,请参见上面的讨论。

正如我在评论中所说的。 是的,从存档中构建没有问题。 (另一种选择是使用
静态加载
功能,但可能会造成性能损失)

我看到您的方法唯一的潜在问题是,您的构造函数几乎可以将任何东西作为参数,这可能会产生问题。 这可能会干扰复制构造函数和其他依赖隐式转换的单参数构造函数

因此,我们必须限制只获取档案

有不同的方法可以做到这一点,但在本次对话中,由于
存档
的继承树已被记录在案,我认为最好的解决方案是检查参数是否来自
basic\u 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
}
#包括
结构Foo{
...
std::矢量数据;
Foo(){
//通过计算填充“数据”
数据回推(1);数据回推(2);
}
模板
Foo(Irchive&ar){
ar>>数据;
//通过读取归档来填充“数据”
}
...    
};
int main(int argc,const char*argv[]
{
//反序列化
boost::archive::text\u iarchive iar(std::cin);
Foo-Foo(iar);//还将与其他档案一起使用
}

至于当您的数据不是默认构造函数时会发生什么,请参见上面的讨论。

是的,为什么不呢?只需在构造函数中添加“ar>>data;”,您就完成了。(真正的挑战是如果“data”是const)@alfC如果“data”没有默认构造函数,您会怎么做?@DavidDoria,正如Alexander Stepanov所说,“如果你不让你的类默认可构造,那么你就得到了你应得的”。所有的类都应该有一个默认构造函数,如果没有(而且你无法控制),你必须在
Foo(归档&ar):data(某物){
,或者在
Foot(归档&ar):data的层次上绕过这个问题(somefunction(ar)){
(但首先有些东西很臭)。@alfC默认构造函数是一件好事吗?它只是爆炸了对象可能处于的状态数(其中大多数状态是坏的/无效的,您必须小心),否?@DavidDoria,您正在将默认构造函数与未初始化的变量混淆。默认构造函数应该使对象保持有效(并且如果可能是可预测的状态)。是的,为什么不呢?只需在构造函数中添加“ar>>data;”,您就完成了。(真正的挑战是如果“data”是const)@如果“数据”没有默认构造函数,你会怎么做?@DavidDoria,正如亚历山大·斯捷潘诺夫所说,“如果你不让你的类默认可构造,那么你就得到了你应得的”。所有类都应该有一个默认的c