I use boost: serialization to save data structures to a file. Actual data is a pointer vector to classes and subclasses. However, the constructor of a class that is serialized takes another instance of the Agent class as a parameter, which is the object that controls communication with the modeling API (webots). I see that in boost :: serialization examples, serializable objects need an empty constructor class () {}; which will be used for reconstruction. However, this is not practical in my case. How can I use reconstruction, but include an object that interacts with the API? One of the serializable classes has this constructor:
State(Agent &A, ACTION_MODE const& m);
and I saw from examples in boost documents that I needed something like this:
State() {};
However, agent & A must be passed as a parameter. Should I find a way around this (using extern, singleton, global object), or is there a way to change this behavior on recovery? I'm sure something is missing here.
thanks
EDIT: Maybe I didn’t explain it enough. I get an error when trying to “download” by restoring serialized data.
error: no matching function to call State::State()
This is what made me look into boost :: serialize code and think that it was invoking a constructor or copy statement. How can I use a specific constructor to serialize data and take agent & a link as an argument?
EDIT # 2:
template <class S, class P, class A> void Task<S,P,A>::save(const char* file) { std::ofstream ofs(file); assert(ofs.good()); boost::archive::text_oarchive oa(ofs); oa << states; ofs.close(); } template <class S, class P, class A> void Task<S,P,A>::load(const char* file) { std::ifstream ifs(file); boost::archive::text_iarchive ia(ifs); ia >> states; ifs.close(); }
States are friend for increasing :: serialization :: access and serialization functions. Saving works fine, loading problem. states: boost::ptr_vector<S> states; where S is the type of polymorphic class of state.
State is a base class and has serialization
template <class Archive> void State::serialize(Archive& ar, const unsigned int version) { ar & accel.Xaxis & accel.Yaxis & accel.Zaxis; ar & gyro.Xaxis & gyro.Yaxis & gyro.Zaxis; ar & gps.Yaxis; ar & positions; ar & reward & value & hash_value; }
guState inherits from state.
template <class Archive> void guState::serialize(Archive& ar, const unsigned int version) { ar & boost::serialization::base_object<State>(*this); ar & accel.Xaxis & accel.Yaxis & accel.Zaxis; ar & gyro.Xaxis & gyro.Yaxis & gyro.Zaxis; ar & gps.Yaxis; ar & positions; ar & reward & value & hash_value; }
accel, gyro, gps - simple structures with three double variables. They are serialized above ^^. Positions are std::map<std::string,float> positions;
Looking at the serialized text file, everything looks OK. I can’t understand why it calls the constructor when trying to load a file.
EDIT # 3:
Base constructor:
State(Agent &A, ACTION_MODE const& m);
Derived Constuctor:
guState::guState(Agent& A, ACTION_MODE const& m) : State(A, m) { ... }
The reference to agents A contained in each state (or derivative state) refers to an object obtained from the modeling API. He controls a robot. I cannot serialize it, and it does not make sense to serialize it.
When i use:
namespace boost { namespace serialization { template <class Archive> void save_construct_data(Archive & ar,const guState* d,const unsigned int file_version) { ar << guState::caller; ar << guState::mode; } template <class Archive> void load_construct_data(Archive & ar, guState* d,const unsigned int file_version) { Agent &a; ACTION_MODE &m; ar >> a; ar >> m; ::new(d) guState(a,m); } } }
I get the following errors:
invalid use of non-static data member State::caller invalid use of non-static data member State::mode
referring to the links used from the constructor. A:
error: 'a' declared as reference but not initialized error: 'm' declared as reference but not initialized
As you can see, it makes no sense to try to save the link to the Agent, because this link (even if it can be saved or serialized) is likely to be different each time the application is launched.
And when loading construction data, except for me, perhaps using the wrong syntax, it makes no sense to build from a serialized link to the agent.
What I need is a way to tell load_construct_data how to get a link to the Agent (after initializing the agent object) and use this link to build the data.
Does that make sense? Do you think this is doable?
Edit # 4
namespace boost { namespace serialization { template <class Archive> void save_construct_data(Archive & ar,const guState* d,const unsigned int file_version) { ar << guState::caller; } template <class Archive> void load_construct_data(Archive & ar, guState* d,const unsigned int file_version) { Agent * a; ACTION_MODE mode = RAND_SING; ar >> a; ::new(d) guState(*a,mode); } } }
This will not allow to serialize guState :: caller
I also serialized the Agent class and overloaded the agent load_construct_data and save_construct_data to request a new instance of the agent to control the API from the modeling application.