我试图在结构化类型的序列化和反序列化之后比较两个映射。它在“MyExample”中给出了错误 - “错误:检查e1_i1->second == e2_i1->second
失败”。
我无法弄清楚以下代码中可能出现的问题:
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/shared_ptr.hpp>
struct A
{
public:
std::string oldname;
std::string newname;
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
ar & oldname;
ar & newname;
}
};
struct Example
{
public:
bool check;
std::map<std::string,boost::shared_ptr<A>> Atype;
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
ar & check;
ar & Atype;
}
};
void set_data(boost::shared_ptr<A> e)
{
e->oldname="a";
e->newname="b";
}
void set_data(Example *e)
{
e->check=false;
// to initialize e->Atype
boost::shared_ptr<A> a1 (new A());
set_data(a1);
e->Atype.insert(std::make_pair("a",a1));
}
void compare_data(std::map<std::string,boost::shared_ptr<A>> e1,std::map<std::string,boost::shared_ptr<A>> e2)
{
// because it is of type map, it may be not in proper order
typedef std::map<std::string,boost::shared_ptr<A>>::const_iterator i1;
i1 e1_i1= e1.begin();
i1 e2_i1 =e2.begin();
while ( e1_i1 != e1.end() && e2_i1 != e2.end())
{
BOOST_CHECK( e1_i1->first == e2_i1->first);
const std::string &key = e1_i1->first;
e2_i1 =e2.find(key);
BOOST_CHECK(e1_i1->second == e2_i1->second);
e1_i1++;
e2_i1++;
}
}
void compare_data(Example *e1,Example *e2)
{
BOOST_CHECK(e1->check == e2->check);
// need to compare e1->Atype with e2->Atype
compare_data(e1->Atype,e2->Atype);
}
BOOST_AUTO_TEST_CASE(MyExample)
{
boost::archive::text_oarchive ao(std::cout);
Example c;
set_data(&c);
const Example & oc=c;
ao << oc;
std::stringstream ss;
boost::archive::text_oarchive oa(ss);
oa << oc;
boost::archive::text_iarchive ia(ss);
Example d;
ia >> d;
compare_data(&c,&d);
}
我确保包含所有头文件,但在这里我没有包括所有。 真的不确定在上面的代码中可能出现什么问题,或者数据的设置值不正确或者比较可能是错误的。
我尝试初始化地图的不同方法:
// e->Atype=map_list_of ("a",a1);
// e->Atype.insert(std::make_pair("a",a1));
// e->Atype.insert(std::map<std::string,boost::shared_ptr<A>>::value_type("a",a1));
// e->Atype["a"]=a1;
谢谢,
答案 0 :(得分:3)
您的比较代码应更改为
void compare_data(const std::map<std::string,boost::shared_ptr<A>>& e1,
const std::map<std::string,boost::shared_ptr<A>>& e2)
{
// because it is of type map, order IS guaranteed
typedef std::map<std::string,boost::shared_ptr<A>>::const_iterator i1;
i1 e1_i1= e1.begin();
i1 e2_i1 =e2.begin();
while ( e1_i1 != e1.end() && e2_i1 != e2.end())
{
BOOST_CHECK( e1_i1->first == e2_i1->first );
if (e1_i1->second) {
// Data value is present on e1, must be present on e2 too
BOOST_CHECK( e2_i1->second );
// The two data values must be equal
BOOST_CHECK( *e1_i1->second == *e2_i1->second ); // Note the *
} else {
// Data value is not present on e1, must not be present in e2 either
BOOST_CHECK( !e2_i1->second );
}
e1_i1++;
e2_i1++;
}
// The iteration must terminate at the same time for e1 and e2
// (i.e. neither of them must have extra elements in respect to the other)
BOOST_CHECK( e1_i1 == e1.end() && e2_i1 == e2.end() );
}
您还应该向bool operator==(const A& other) const
课提供A
,以检查A
的两个实例是否具有相同的值。
当反序列化时,要求在同一个内存地址中分配对象没有意义,只有查看重新加载的值是否相同才有意义。
答案 1 :(得分:1)
// because it is of type map, it may be not in proper order
相反,map
是有序容器,而且不变量恰恰是元素始终按正确顺序。
序列化很好:Coliru两次打印相同的数据:
22 serialization::archive 10 0 0 0 0 0 1 0 0 0 1 a 0 1 4 1 0
0 1 a 1 b
22 serialization::archive 10 0 0 0 0 0 1 0 0 0 1 a 0 1 4 1 0
0 1 a 1 b
所以这是比较被打破了。解决它:
MapOfA mapOfA;
bool operator==(Example const& other) const {
return (check == other.check)
&& (mapOfA.size() == other.mapOfA.size())
&& (mapOfA.end() == std::mismatch(
mapOfA.begin(), mapOfA.end(),
other.mapOfA.begin(),
&ComparePair
).first);
}
private:
typedef MapOfA::value_type Pair;
static bool ComparePair(Pair const& a, Pair const& b) {
bool ok = (a.first == b.first);
if (a.second || b.second)
ok &= (a.second && b.second) && (*a.second == *b.second);
return ok;
}
当你不使用指针和辅助函数时,你会发现整个程序变得更小,更不容易出错。相反,尽可能使用** const&
引用和标准惯用法/算法。
以下是97 lines Live On Coliru中程序的一个版本。
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <sstream>
struct A
{
std::string oldname;
std::string newname;
A(std::string oldname = "", std::string newname = "")
: oldname(std::move(oldname)), newname(std::move(newname))
{ }
bool operator==(A const& other) const {
return (oldname == other.oldname)
&& (newname == other.newname);
}
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive &ar, unsigned) {
ar & oldname;
ar & newname;
}
};
struct Example
{
typedef std::map<std::string, boost::shared_ptr<A> > MapOfA;
bool check;
MapOfA mapOfA;
bool operator==(Example const& other) const {
return (check == other.check)
&& (mapOfA.size() == other.mapOfA.size())
&& (mapOfA.end() == std::mismatch(
mapOfA.begin(), mapOfA.end(),
other.mapOfA.begin(),
&ComparePair
).first);
}
private:
typedef MapOfA::value_type Pair;
static bool ComparePair(Pair const& a, Pair const& b) {
bool ok = (a.first == b.first);
if (a.second || b.second)
ok &= (a.second && b.second) && (*a.second == *b.second);
return ok;
}
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive &ar, unsigned) {
ar & check;
ar & mapOfA;
}
};
template <typename T>
std::string to_string(T const& o) {
std::stringstream ss;
boost::archive::text_oarchive oa(ss);
oa << o;
return ss.str();
}
int main()
{
Example const data = {
false,
{ { "ONE", boost::make_shared<A>("old one","new one") },
{ "TWO", boost::make_shared<A>("old two","new two") },
{ "TRHEE", boost::make_shared<A>("old three","new three") },
}
};
std::string const original = to_string(data);
std::cout << original << "\n";
{
std::stringstream ss(original);
boost::archive::text_iarchive ia(ss);
Example roundtrip;
ia >> roundtrip;
std::string const verification = to_string(roundtrip);
std::cout << std::boolalpha;
std::cout << "Matching: " << (data == roundtrip) << "\n";
std::cout << "Serialized: " << (verification == original) << "\n";
}
}