我正在使用boost图库。我需要序列化一个 图形对象,稍后再读出来。但我发现了我的 程序无法与XML归档程序一起正常工作。它 总是抛出异常的说法:
XML开始/结束标记 不匹配 - 位置。
我没有定义一个名为的标签
我的序列化代码中的"position"
。我不知道怎么回事
解决它。这是一个演示
这个问题。
#ifndef TYPES_H
#define TYPES_H
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/adj_list_serialize.hpp>
#include <boost/graph/filtered_graph.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/deque.hpp>
#include <boost/serialization/variant.hpp>
#include <boost/variant.hpp>
#include <boost/ref.hpp>
using namespace boost;
namespace bmi = boost::multi_index;
class QTable; //forward declaration
typedef QTable Eligibility;
//观测类型
enum Observation{present,absent,idle};
//1)图模型的定义
enum vertex_BatteryLevel_t {vertex_BatteryLevel};
enum vertex_ObservationHistory_t {vertex_ObservationHistory};
enum edge_QFunction_t {edge_QFunction};
enum edge_Eligibility_t {edge_Eligibility};
namespace boost {
BOOST_INSTALL_PROPERTY(vertex,BatteryLevel);
BOOST_INSTALL_PROPERTY(vertex,ObservationHistory);
BOOST_INSTALL_PROPERTY(edge,QFunction);
BOOST_INSTALL_PROPERTY(edge,Eligibility);
}
typedef property<vertex_BatteryLevel_t,int,
property<vertex_ObservationHistory_t,std::deque<Observation>,
property<vertex_index_t,int>
>
> vertex_state;
typedef property<edge_QFunction_t,QTable,
property<edge_Eligibility_t,Eligibility>
> edge_qfunction;
typedef adjacency_list<
vecS,setS,directedS, //结点用vecSå› ä¸ºæ— éœ€åŠ¨æ€æ”¹å˜ç»“点个数,用setS表示边为了强调是简å•å›¾ï¼ˆä¸¤ä¸ªç»“点之间一个方å‘çš„è¾¹åªèƒ½æœ‰ä¸€æ¡ï¼‰
vertex_state, //节点的电é‡å’Œè§‚测历å²
edge_qfunction //æ¯ä¸ªæœ‰å‘边对应一个ublas::matrix<double>对象属性
> Graph;
//2)Q函数的定义
//行为类型
enum NotSensing{off=-2,recharge=-1};
typedef variant<int,NotSensing> Action; //action={å„个方å‘,off,recharge}
//state=<历å²è§‚测,ç”µæ± ç”µé‡>
struct Status {
friend class boost::serialization::access;
template<class Archive> void serialize(Archive & ar,const unsigned int version);
//从结点id->观测历å²çš„æ˜ å°„
//æ¯ä¸€ä¸ªæ—¶åˆ»çš„历å²è§‚测顺åºæ˜¯ä¼ 感器本身,按照è¿ä»£å™¨é¡ºåºçš„å…¶ä»–ä¼ æ„Ÿå™¨è§‚æµ‹
typedef std::map<int,std::deque<Observation> > HistoryType;
HistoryType history;
int batteryLevel; //ç”µæ± ç”µé‡
Status() {}
Status(const HistoryType & h,const int & bl);
Status(const Status & s);
~Status() {}
friend bool operator<(const Status & idx1,const Status & idx2);
friend bool operator==(const Status & idx1,const Status & idx2);
};
template<class Archive>
inline void Status::serialize(Archive & ar,const unsigned int)
{
ar & boost::serialization::make_nvp("history",history);
ar & boost::serialization::make_nvp("batteryLevel",batteryLevel);
}
struct QTableElem {
friend class boost::serialization::access;
template<class Archive> void serialize(Archive &,const unsigned int) {}
Status status;
Action myaction, youraction;
double value;
QTableElem(const Status & s,const Action & ma,const Action & ya,double v)
: status(s),myaction(ma),youraction(ya),value(v) {}
};
typedef QTableElem EligibilityElem;
//å› ä¸ºtypedefä¸èƒ½circular dependent所以需è¦å®šä¹‰ä¸ªç±»ç»§æ‰¿å…¶ä¸ä¸€ä¸ªtypedef。
class QTable : public bmi::multi_index_container <
QTableElem,
bmi::indexed_by <
bmi::ordered_unique<
bmi::composite_key<
QTableElem,
bmi::member<QTableElem,Status,&QTableElem::status>,
bmi::member<QTableElem,Action,&QTableElem::myaction>,
bmi::member<QTableElem,Action,&QTableElem::youraction>
>
>,
bmi::ordered_non_unique<bmi::member<QTableElem,Status,&QTableElem::status> >
>
> {};
namespace boost {
namespace serialization {
template<class Archive> inline void save_construct_data(Archive & ar,const QTableElem * e,const unsigned int) {
ar << boost::serialization::make_nvp("status",e->status);
ar << boost::serialization::make_nvp("myaction",e->myaction);
ar << boost::serialization::make_nvp("youraction",e->youraction);
ar << boost::serialization::make_nvp("value",e->value);
}
template<class Archive> void load_construct_data(Archive & ar,QTableElem * e,const unsigned int) {
Status s;
Action ma,ya;
double v;
ar >> boost::serialization::make_nvp("status",s);
ar >> boost::serialization::make_nvp("myaction",ma);
ar >> boost::serialization::make_nvp("youraction",ya);
ar >> boost::serialization::make_nvp("value",v);
::new(e) QTableElem(s,ma,ya,v);
}
}
}
#endif
#include <stdexcept>
#include "types.h"
Status::Status(const Status::HistoryType & h,const int & bl)
:history(h),batteryLevel(bl)
{
}
Status::Status(const Status & s)
:history(s.history),batteryLevel(s.batteryLevel)
{
}
bool operator<(const Status & idx1,const Status & idx2)
{
#ifndef NDEBUG
assert(idx1.history.size() == idx2.history.size());
#endif
Status::HistoryType::const_iterator it,it2;
for(it = idx1.history.begin(), it2 = idx2.history.begin() ; it != idx1.history.end() && it2 != idx2.history.end() ; it++,it2++) {
#ifndef NDEBUG
assert(it->first == it2->first);
assert(it->second.size() == it2->second.size());
#endif
std::deque<Observation>::const_iterator itt,itt2;
for(itt = it->second.begin(), itt2 = it2->second.begin() ; itt != it->second.end() && itt2 != it2->second.end() ; itt++,itt2++) {
if(*itt < *itt2) return true;
if(*itt > *itt2) return false;
}
}
#ifndef NDEBUG
assert(it == idx1.history.end() && it2 == idx2.history.end());
#endif
return false;
}
bool operator==(const Status & idx1,const Status & idx2)
{
#ifndef NDEBUG
assert(idx1.history.size() == idx2.history.size());
#endif
Status::HistoryType::const_iterator it, it2;
for(it = idx1.history.begin(), it2 = idx2.history.begin() ; it != idx1.history.end() && it2 != idx2.history.end() ; it++,it2++) {
#ifndef NDEBUG
assert(it->first == it2->first);
assert(it->second.size() == it2->second.size());
#endif
std::deque<Observation>::const_iterator itt,itt2;
for(itt = it->second.begin(), itt2 = it2->second.begin() ; itt != it->second.end() && itt2 != it2->second.end() ; itt++,itt2++) {
if(*itt != *itt2) return false;
}
}
#ifndef NDEBUG
assert(it == idx1.history.end() && it2 == idx2.history.end());
#endif
return true;
}
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include "types.h"
//compile with "g++ main.cpp types.cpp -I. -o test -lboost_serialization"
int main()
{
using boost::serialization::make_nvp;
{
//load vertices
std::ifstream in("../graph.txt");
if (false == in.is_open())
throw std::runtime_error("invalid graph model file!");
typedef graph_traits<Graph>::vertices_size_type size_type;
size_type n_vertices;
in >> n_vertices;
std::istream_iterator<std::pair<size_type, size_type> > input_begin(in), input_end;
Graph g(input_begin, input_end, n_vertices);
//serialize the graph object
{
std::ofstream out("../test.xml");
if (false == out.is_open()) throw std::runtime_error("invalid file!");
boost::archive::xml_oarchive oa(out);
oa << make_nvp("graph", g);
}
}
{
//deserialize from the file
std::ifstream xml("../test.xml");
if (false == xml.is_open())
throw std::runtime_error("invalid file!");
{
boost::archive::xml_iarchive ia(xml);
Graph g;
try {
ia >> make_nvp("graph", g);
}
catch (boost::archive::archive_exception const& ae)
{
std::cout << "Error: " << ae.code << ":'" << ae.what() << "'\n";
}
}
}
}
namespace std {
template <typename T> istream & operator>>(istream & in,pair<T,T>& p) {
in >> p.first >> p.second;
return in;
}
}
答案 0 :(得分:4)
一如既往
如果出现意外故障:
如果你这样做了,你很快就发现了
Eligibility e;
oa << make_nvp("e", e);
接着是
ia >> make_nvp("e", e);
即使没有任何数据,也会显示完全相同的问题。问题是来自QTable
的{{1}} 派生,这打破了它的序列化实现。
这里是最小的复制者 Live On Coliru
boost::multi_index_container
打印
namespace bmi = boost::multi_index;
struct QTableElem {
template<class Archive> void serialize(Archive &ar,const unsigned int) {
ar & boost::serialization::make_nvp("dummy", dummy);
}
int dummy;
};
class QTable : public bmi::multi_index_container<
QTableElem,
bmi::indexed_by<
bmi::ordered_unique<bmi::member<QTableElem,int,&QTableElem::dummy> >
>
> {};
int main()
{
using boost::serialization::make_nvp;
{
std::ofstream out("test.xml");
boost::archive::xml_oarchive oa(out);
QTable obj;
oa << make_nvp("graph", obj);
}
try {
std::ifstream xml("test.xml");
boost::archive::xml_iarchive ia(xml);
QTable obj;
ia >> make_nvp("graph", obj);
} catch (boost::archive::archive_exception const& ae) {
std::cout << "Error: " << ae.code << ":'" << ae.what() << "'\n";
}
}
注意:错误实际上与关闭元素的关系(W3C&#39;良好格式检查也会告诉你)
现在,要修复SSCCE,只需删除继承:
<强> Live On Coliru 强>
g++ -std=c++03 -O2 -Wall -pedantic -pthread main.cpp -lboost_system -lboost_serialization && ./a.out
Error: 1:'position'
我为您的图表示例做了同样的事情。它起作用(根据测试完全执行):
typedef bmi::multi_index_container<
QTableElem,
bmi::indexed_by<
bmi::ordered_unique<bmi::member<QTableElem,int,&QTableElem::dummy> >
>
> QTable;
如果您想查看它,请参阅:https://gist.github.com/sehe/093f823937486eb99d2f