Boost serialization of a child class

I have a base class User that is serializable:

class User { public: User(); std::string GetLogin() const; void SetLogin(std::string login); protected: std::string mLogin; friend class boost::serialization::access; template<class Archive> void serialize(Archive & ar, const unsigned int version) { ar & mLogin; } }; 

This class can be inherited by another class as follows:

 class UserA : public User { UserA(); private: friend class boost::serialization::access; template<class Archive> void serialize(Archive & ar, const unsigned int version) { ar & boost::serialization::base_object<User>(*this); ar & mIsSomething; } bool mIsSomething = true; } 

To handle this user, I have a class "manager" that contains the user vector:

 class Manager { public: bool Add(User user); bool Remove(unsigned int index); private: std::vector<User> mUsers; friend class boost::serialization::access; template<class Archive> void serialize(Archive & ar, const unsigned int version) { ar & mUsers; } }; 

Thus, my manager can be populated with UserA or UserB (both do not work at the same time). When I retrieve an item from Manager , I simply return it back to the correct child class. This part is working fine.

But when I want to serialize the Manager class, obviously, Boost does not know what type of User I am trying to serialize, and the additional fields from the child class are not serialized.

What is my solution here? Is my project completely wrong?
Should I specialize my manager class to something like this?

 class Manager { bool Add(UserA user); bool Add(UserB user); private: std::vector<UserA> mUsersA; std::vector<UserB> mUsersB; } 
+1
c ++ inheritance boost serialization boost-serialization
Oct 27 '15 at 10:12
source share
1 answer

So my manager can be populated with UserA or UserB (both of them are both at the same time)

No he can not:

 std::vector<User> mUsers; 

stores User objects by value. See What is cropping objects? .

Thoughts

I also suggest an admin template for a specific user type, but seeing how you use the actual type hierarchy, it looks like you really want to use run-time polymorphism.

Since serializing polymorphic types is somewhat more complex, let me show you a sample.

It also shows how to use, for example. boost::ptr_vector<> for managing objects when they are dynamically stored.

Live 1 at Coliru

 #include <boost/archive/text_iarchive.hpp> #include <boost/archive/text_oarchive.hpp> #include <boost/ptr_container/ptr_vector.hpp> #include <boost/ptr_container/serialize_ptr_vector.hpp> #include <boost/serialization/serialization.hpp> #include <boost/serialization/access.hpp> #include <boost/serialization/base_object.hpp> #include <boost/serialization/export.hpp> #include <boost/serialization/string.hpp> #include <boost/serialization/vector.hpp> class User { public: User() {}; virtual ~User() {} std::string GetLogin() const; void SetLogin(std::string login); protected: std::string mLogin; friend class boost::serialization::access; template<class Archive> void serialize(Archive & ar, const unsigned int /*version*/) { ar & mLogin; } }; class UserA : public User { public: UserA() {}; private: friend class boost::serialization::access; template<class Archive> void serialize(Archive & ar, const unsigned int /*version*/) { ar & boost::serialization::base_object<User>(*this); ar & mIsSomething; } bool mIsSomething = true; }; class UserB : public User { public: UserB() {}; private: friend class boost::serialization::access; template<class Archive> void serialize(Archive & ar, const unsigned int /*version*/) { ar & boost::serialization::base_object<User>(*this); ar & mIsSomethingElse; } bool mIsSomethingElse = true; }; template <typename Tag> class UserGen : public User { public: UserGen() {}; private: friend class boost::serialization::access; template<class Archive> void serialize(Archive & ar, const unsigned int /*version*/) { ar & boost::serialization::base_object<User>(*this); ar & mIsGen; } bool mIsGen = true; }; struct GenA; struct GenB; struct GenC; BOOST_CLASS_EXPORT(User) BOOST_CLASS_EXPORT(UserA) BOOST_CLASS_EXPORT(UserB) BOOST_CLASS_EXPORT(UserGen<GenA>) BOOST_CLASS_EXPORT(UserGen<GenB>) BOOST_CLASS_EXPORT(UserGen<GenC>) #include <boost/type_index.hpp> class Manager { public: template <typename User> bool Add(User const& user) { mUsers.push_back(new User(user)); return true; // FIXME? } bool Remove(unsigned int index) { if (mUsers.size() > index) { mUsers.erase(mUsers.begin()+index); return true; } return false; } void dump() const { for (auto& u : mUsers) { std::cout << "user of type " << boost::typeindex::type_id_runtime(u) << "\n"; } } private: boost::ptr_vector<User> mUsers; friend class boost::serialization::access; template<class Archive> void serialize(Archive & ar, const unsigned int /*version*/) { ar & mUsers; } }; #include <sstream> #include <iostream> int main() { std::stringstream ss; { Manager man; man.Add(UserA{}); man.Add(UserB{}); man.Add(UserGen<GenA>{}); man.Add(UserGen<GenB>{}); man.Add(UserGen<GenC>{}); boost::archive::text_oarchive oa(ss); oa << man; } { boost::archive::text_iarchive ia(ss); Manager man; ia >> man; man.dump(); } } 

Print

 user of type UserA user of type UserB user of type UserGen<GenA> user of type UserGen<GenB> user of type UserGen<GenC> 



1 link boost 1.59 somehow fails :( Thanks @ ms. To calculate 1.58 still works

+1
Oct 27 '15 at 10:19
source share



All Articles