gpt4 book ai didi

c++ - boost 序列化: forward compatibility fail with input stream error

转载 作者:行者123 更新时间:2023-11-30 05:32:39 28 4
gpt4 key购买 nike

以下问题:Boost serialize child class我正在尝试支持通过 boost 序列化生成的存档的向前兼容性,但我无法使用旧代码读取较新的存档:

    class A {
public:
A() {}
virtual ~A() = default;

private:
friend class boost::serialization::access;
template <class Archive> void serialize(Archive &ar, const unsigned int version) {
ar &mAttributeFromA;
}

std::string mAttributeFromA = "mAttributeFromA";
};
BOOST_CLASS_VERSION(A, 0)

class B : public A {
public:
B() {}

private:
friend class boost::serialization::access;
template <class Archive> void serialize(Archive &ar, const unsigned int version)
{
ar &boost::serialization::base_object<A>(*this);
ar &mAttributeFromB;
if (version == 1)
ar &mNewAttribute;
}

std::string mAttributeFromB = "mAttributeFromB";
std::string mNewAttribute = "mNewAttribute";
};

BOOST_CLASS_VERSION(B, 1)


class Manager {
public:
boost::ptr_vector<A> mListOfA; // can store A or B
private:
friend class boost::serialization::access;

template <class Archive> void serialize(Archive &ar, const unsigned int /*version*/) { ar &mListOfA; }
};
BOOST_CLASS_VERSION(Manager, 0)


int main() {
Manager mgr;
mgr.mListOfA.push_back(new B);
mgr.mListOfA.push_back(new B);

std::ofstream ofs("myFile.txt");
{
boost::archive::text_oarchive oa(ofs);
oa << mgr;
}

try {
Manager mgr2;
std::ifstream ifs("myFile.txt");
boost::archive::text_iarchive ia(ifs);
ia >> mgr2;
mgr2.mListOfA.at(0);
} catch(boost::archive::archive_exception e)
{
e.what();
}
}
BOOST_CLASS_EXPORT(A)
BOOST_CLASS_EXPORT(B)

这将生成以下存档:

22 serialization::archive 13 0 0 0 0 2 3 1 B 1 1
0 1 0
1 15 mAttributeFromA 15 mAttributeFromB 13 mNewAttribute 3
2
3 15 mAttributeFromA 15 mAttributeFromB 13 mNewAttribute

如果我尝试使用相同的代码重新加载存档,一切都会完美无缺。

但是,如果我尝试使用旧版本的代码加载存档:(类版本为 0 并且 mNewAttribute 消失了)

class B : public A {
public:
B() {}

private:
friend class boost::serialization::access;
template <class Archive> void serialize(Archive &ar, const unsigned int version)
{
ar &boost::serialization::base_object<A>(*this);
ar &mAttributeFromB;
}

std::string mAttributeFromB = "mAttributeFromB";
};

BOOST_CLASS_VERSION(B, 0)

反序列化抛出一个“输入流错误

On Coliru

如何使用旧代码反序列化新存档?

-- 编辑--奇怪的是,如果我在管理器中添加 A B 对象,它就会工作。但是只有 A 或 B 失败 ...

最佳答案

您的类型不是多态的。版本控制可能与事情无关。

  • http://www.boost.org/doc/libs/1_60_0/libs/serialization/doc/serialization.html#derivedpointers

    It turns out that the kind of object serialized depends upon whether the base class (base in this case) is polymophic or not. If base is not polymorphic, that is if it has no virtual functions, then an object of the type base will be serialized. Information in any derived classes will be lost. If this is what is desired (it usually isn't) then no other effort is required.

你可以很容易地验证这一点: vector 只反序列化 As:

Live On Coliru

#include <boost/serialization/serialization.hpp>
#include <boost/serialization/version.hpp>

class A {
public:
A(){}

private:
friend class boost::serialization::access;
template <class Archive> void serialize(Archive &ar, const unsigned int version) { ar &mAttributeFromA; }

std::string mAttributeFromA = "mAttributeFromA";
};
BOOST_CLASS_VERSION(A, 0)

class B : public A {
public:
B(){}

private:
friend class boost::serialization::access;
template <class Archive> void serialize(Archive &ar, const unsigned int version) {
ar &mAttributeFromB;
if (version == 1)
ar &mNewAttribute;
}

std::string mAttributeFromB = "mAttributeFromB";
std::string mNewAttribute = "mNewAttribute";
};

BOOST_CLASS_VERSION(B, 1)

#include <boost/ptr_container/serialize_ptr_vector.hpp>

class Manager {
public:
boost::ptr_vector<A> mListOfA; // can store A or B
private:
friend class boost::serialization::access;

template <class Archive> void serialize(Archive &ar, const unsigned int /*version*/) { ar &mListOfA; }
};
BOOST_CLASS_VERSION(Manager, 0)

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <sstream>

int main() {
using namespace boost;

std::stringstream ss;

{
archive::text_oarchive oa(ss);
Manager mgr;
mgr.mListOfA.push_back(new A);
mgr.mListOfA.push_back(new B);

oa << mgr;
}

std::cout << ss.str() << "\n";

{
archive::text_iarchive ia(ss);
Manager mgr;

ia >> mgr;

std::cout << "Deserialized: " << mgr.mListOfA.size() << "\n";
}
}

打印

22 serialization::archive 13 0 0 0 0 2 2 1 0
0 15 mAttributeFromA 2
1 15 mAttributeFromA

Deserialized: 2

解决方案:

  1. 使层次结构实际上是多态的
  2. 添加基础对象的序列化
  3. 注册派生类型
  4. ???
  5. 利润!

sample (在制品)https://www.livecoding.tv/sehe/

Live On Coliru

#include <boost/serialization/serialization.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/version.hpp>

class A {
public:
A(){}
virtual ~A() = default;

private:
friend class boost::serialization::access;
template <class Archive> void serialize(Archive &ar, const unsigned int version) {
ar &mAttributeFromA;
}

std::string mAttributeFromA = "mAttributeFromA";
};
BOOST_CLASS_VERSION(A, 0)

class B : public A {
public:
B(){}

private:
friend class boost::serialization::access;
template <class Archive> void serialize(Archive &ar, const unsigned int version)
{
ar &boost::serialization::base_object<A>(*this);
ar &mAttributeFromB;
if (version == 1)
ar &mNewAttribute;
}

std::string mAttributeFromB = "mAttributeFromB";
std::string mNewAttribute = "mNewAttribute";
};

BOOST_CLASS_VERSION(B, 1)
BOOST_CLASS_EXPORT(A)
BOOST_CLASS_EXPORT(B)

#include <boost/ptr_container/serialize_ptr_vector.hpp>

class Manager {
public:
boost::ptr_vector<A> mListOfA; // can store A or B
private:
friend class boost::serialization::access;

template <class Archive> void serialize(Archive &ar, const unsigned int /*version*/) { ar &mListOfA; }
};
BOOST_CLASS_VERSION(Manager, 0)

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <sstream>

int main() {
using namespace boost;

std::stringstream ss;

{
archive::text_oarchive oa(ss);
Manager mgr;
mgr.mListOfA.push_back(new A);
mgr.mListOfA.push_back(new B);

oa << mgr;
}

std::cout << ss.str() << "\n";

{
archive::text_iarchive ia(ss);
Manager mgr;

ia >> mgr;

std::cout << "Deserialized: " << mgr.mListOfA.size() << "\n";
}
}

打印

22 serialization::archive 13 0 0 0 0 2 2 1 0
0 15 mAttributeFromA 3 1 B 1 1
1
2 15 mAttributeFromA 15 mAttributeFromB 13 mNewAttribute

Deserialized: 2

关于c++ - boost 序列化: forward compatibility fail with input stream error,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35055936/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com