How can I serialize std::type_info using Boost serialization?
I want to record the std::type_info
of a variable so that on load I will be able to re-create the appropriate type variable.
Saving will look like this:
friend class boost::serialization::access;
template<class Archive>
void save(Archive & ar, const unsigned int version) const
{
...
开发者_StackOverflow ar & BOOST_SERIALIZATION_NVP(typeid(value));
ar & BOOST_SERIALIZATION_NVP(value);
...
}
Loading will look like this:
template<class Archive>
void load(Archive & ar, const unsigned int version)
{
...
std::type_info currentType;
ar & BOOST_SERIALIZATION_NVP(currentType);
if(currentType.name() == typeid(std::string).name())
{
std::string value;
ar & BOOST_SERIALIZATION_NVP(value);
//this next line is why I need to read back the type
someObject.setValue<std::string>(value);
}
... //else if for all other types
}
Or, if you have any other ideas for a way to solve this I am open to suggestions. I feel like I am going about this in the wrong way.
I don't know if this is exactly what you're looking for, and this is certainly a different approach from what you have so far, so YMMV... but in the past I have accomplished a similar goal by creating a type hierarchy and then using Boost.Serialization's ability to automatically serialize/deserialize a pointer to a polymorphic type. This has the benefit of not having to muck with any RTTI in your code (the library may be doing RTTI under the hood - I'm not sure), but does have a few drawbacks.
For one, it certainly makes the code more complicated IMO. You may be dealing with types in the code that you can't easily modify or work into a hierarchy. You also may not be willing to take the (relatively small) performance hit of polymorphism and heap allocation.
Here's a more or less complete example. The visitor pattern is useful here since you may want just a very thin wrapper around existing types that might not have anything in common:
#include <boost/serialization/export.hpp>
class Visitor;
class Base
{
public:
virtual ~Base() { }
virtual void accept(const Visitor & v) = 0;
protected:
friend class boost::serialization::access;
template <typename Archive>
void serialize(Archive & ar, const unsigned int version)
{ }
};
/* specialization for one set of types */
class Type1 : public Base
{
public:
virtual ~Type1() { }
virtual void accept(const Visitor & v) { ... }
protected:
friend class boost::serialization::access;
template <typename Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & boost::serialization::base_object<Base>(*this);
ar & m_dataType1;
ar & m_dataType2;
//etc...
}
//member data follows...
};
/* specialization for some other set of types */
class Type2 : public Base
{
public:
virtual ~Type2() { }
virtual void accept(const Visitor & v) { ... }
protected:
friend class boost::serialization::access;
template <typename Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & boost::serialization::base_object<Base>(*this);
ar & m_dataType1;
ar & m_dataType2;
//etc...
}
};
BOOST_CLASS_EXPORT_GUID(Type1, "Type1")
BOOST_CLASS_EXPORT_GUID(Type2, "Type2")
The BOOST_CLASS_EXPORT_GUID
is required to "register" the derived types with the library so that it can identify them uniquely within the archive. For a more complete explanation, see the section titled "Pointers to Objects of Derived Classes" on this page
Now you can serialize and deserialize using a pointer to the base class (can even used shared_ptr
;), and use the visitor pattern (or some other method) to access the data via polymorphism at runtime, e.g.:
boost::shared_ptr<Base> p;
...
p.reset(new Type1(...));
archive << p;
p.reset(new Type2(...));
archive << p;
...
archive >> p; //p now points to a Type1
archive >> p; //p now points to a Type2
This question and answer may also be useful: Boost Serialization using polymorphic archives
Hope this helps!
EDIT: fixed my link to the Boost docs...
精彩评论