我需要将包含hash_map的对象序列化为另一个对象作为键。用作键的对象是其他对象的基类。我已经在基类和派生类中实现了serialize()方法,并且每个派生类都继承了基类的序列化方法。情况类似于:
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/hash_map.hpp>
#include <boost/serialization/base_object.hpp>
class Item {
protected:
unsigned int _refc;
static unsigned int _total_alloc;
//other code
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & _refc;
ar & _total_alloc;
}
};
class StringItem : public Item {
private:
string _s;
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & boost::serialization::base_object<Item>(*this);
ar & _s;
}
};
这是我需要序列化的类:
class TokenFinder : public Model {
public:
TokenFinder(void);
virtual ~TokenFinder(void);
virtual void insert_item(Item *item);
private:
/** Map to store tokens together with their number of occurrences.
*/
__gnu_cxx::hash_map<Item *, unsigned long> _elements;
unsigned long _element_count;
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & _elements; //Error when saved
ar & _element_count;
}
};
当我尝试序列化TokenFinder对象时,错误是:在抛出'boost :: archive :: archive_exception'的实例后调用terminate what():未注册的类 - 未注册或导出的派生类
有什么建议吗?提前谢谢!
答案 0 :(得分:1)
尝试在使用之前使用Archive注册Item的子类:
template<class Archive>
void serialize(Archive & ar, unsigned)
{
ar.template register_type<StringItem>(); // THIS
ar & boost::serialization::base_object<Model>(*this);
ar & _elements;
ar & _element_count;
}
输出
22 serialization::archive 10 0 0 0 0 0 0 6 0 0 0 1 1 0
0 1 0
1 0 10 cow-jumped 6 1
2
3 0 4 moon 5 1
4
5 0 4 lazy 4 1
6
7 0 3 the 3 1
8
9 0 5 world 2 1
10
11 0 5 hello 1 0
注释
std::unordered_map
定义了序列化,因此您不再需要使用已弃用的GNU库扩展(另请参阅this bug-report/patch)_total_alloc
因为,当然,您不希望这个号码被反序列化Item
的生命周期/分配作为练习进行管理(我不知道你希望如何组织所有权语义)。#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <unordered_map>
#include <boost/serialization/collections_save_imp.hpp>
#include <boost/serialization/collections_load_imp.hpp>
#include <boost/serialization/utility.hpp>
#include <boost/serialization/split_free.hpp>
namespace boost { namespace serialization {
template<class Archive, typename... TArgs >
inline void save(Archive & ar, std::unordered_map<TArgs...> const&t, unsigned) {
boost::serialization::stl::save_collection<Archive, std::unordered_map<TArgs...> >(ar, t);
}
template<class Archive, typename... TArgs >
inline void load(Archive & ar, std::unordered_map<TArgs...> &t, unsigned) {
boost::serialization::stl::load_collection<Archive,
std::unordered_map<TArgs...>,
boost::serialization::stl::archive_input_map<
Archive, std::unordered_map<TArgs...> >,
boost::serialization::stl::no_reserve_imp<std::unordered_map<TArgs...> >
>(ar, t);
}
// split non-intrusive serialization function member into separate
// non intrusive save/load member functions
template <class Archive, typename... TArgs>
inline void serialize(Archive & ar, std::unordered_map<TArgs...> &t, unsigned file_version) {
boost::serialization::split_free(ar, t, file_version);
}
} }
#include <boost/serialization/base_object.hpp>
class StringItem;
class Item {
protected:
unsigned int _refc;
static unsigned int _total_alloc;
//other code
Item() : _refc(0) { }
virtual ~Item() {}
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, unsigned)
{
ar & _refc;
//ar & _total_alloc; // wut? a static?!
}
};
/*static*/ unsigned int Item::_total_alloc;
class StringItem : public Item {
public:
StringItem(std::string s = "") : _s(std::move(s)) { }
private:
std::string _s;
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, unsigned)
{
ar & boost::serialization::base_object<Item>(*this);
ar & _s;
}
};
struct Model {
virtual ~Model() {}
template<class Archive> void serialize(Archive&r, unsigned) { }
};
class TokenFinder : public Model
{
public:
TokenFinder(void) : _element_count(0) {}
virtual ~TokenFinder(void) {}
virtual void insert_item(Item *item) { _elements[item] = _elements.size()+1; }
private:
/** Map to store tokens together with their number of occurrences. */
std::unordered_map<Item*, unsigned long> _elements;
unsigned long _element_count;
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, unsigned)
{
ar.template register_type<StringItem>();
ar & boost::serialization::base_object<Model>(*this);
ar & _elements;
ar & _element_count;
}
};
int main()
{
boost::archive::text_oarchive oa(std::cout);
std::vector<StringItem> seed_data {
{"hello"},{"world"},{"the"},{"lazy"},{"moon"}, {"cow-jumped"}
};
TokenFinder tf;
for(auto& si : seed_data)
tf.insert_item(&si);
oa << tf;
}