0

I am trying to work with boost::serialisation for saving and loading some objects. So far from the boost::tutorial I have managed to do things work for all the different stl stuff (vectors, pairs, lists etc), for derived classes, for boost multi-arrays and other things, but I am stuck trying to work around how to serialize a boost::any vector. Let me say in advance that I found and checked in the forum some posts for boost::varian serialization and even one for boost::any (which even has an almost identical title) but yet again I didn't manage to solve my problems. So let me go with a small example:

Say I have this class:

 class class_2
 {
   private:

     template<class Archive>
     void serialize(Archive & ar, const unsigned int version)
      {
         ar & degrees;
         ar & minutes;
         ar & seconds;

      for( std::vector<boost::any>::iterator it = v_any.begin() ; it != v_any.end() ; ++it  ) {
        //Trying to cast all the possible types that may enter the 
        //boost any vector, for the sake of this example let's just 
        //say that we will only pass a second class called name class_1
        //to the boost::any vector and we only have to cast this class
        if (it->type() == typeid(class_1)){
            class_1 lan = boost::any_cast< class_1 > (*it );
                ar &  (lan);
        }

       }// for boost::any*/
   } //serialization
   public:
      int degrees;
      int minutes;
     float seconds;


     class_2(){};
     class_2(int d, int m, float s) :
       degrees(d), minutes(m), seconds(s)
         {}

   std::vector<boost::any> v_any;
 };

And to be more precise the class_1 that we expect for this small example to exist inside the boost::any vector is the following class:

 class class_1
 {
    private:
    friend class boost::serialization::access;
     template<class Archive>
     void serialize(Archive & ar, const unsigned int version)
     {
        ar & a;
     }

     public:
     class_1(){};
     int a;
    };

So when I compile the above code with a main function where I save and load an object of class_2 that containts inside the boost::any vector an object of class_1 everything compiles and even runs:

int main() {

class_1 alpha;
class_2 beta;

alpha.a=5;
beta.v_any.push_back(alpha);

    std::ofstream ofs("file");
// save data to archive
{
    boost::archive::text_oarchive oa(ofs);
    // write class instance to archive
    oa << beta;
    // archive and stream closed when destructors are called
}

// ... some time later restore the class instance to its orginal state
class_2 newclass;
{
    // create and open an archive for input
    std::ifstream ifs("file");
    boost::archive::text_iarchive ia(ifs);
    // read class state from archive
    ia >> newclass;
    // archive and stream closed when destructors are called
}

return 0;
}

Yet again the loaded newclass object has an empty boost::any vector with nothing saved inside. So my question is what am I doing wrong in the above code and what should I change in order to serialize the boost::any vector correctly..? Any help/suggestion would be very appreciated.

user3111197
  • 83
  • 2
  • 11
  • In `class_2::serialize` you don't seem to store the size of the vector -- when you begin deserializing, the vector is empty, so the for loop will not run, and none of the contained objects will be loaded. i.e. it has nothing to do with `boost::any`, you're simply not handling the vector correctly. – Dan Mašek May 17 '16 at 14:03
  • Thanks a lot for your answer. I am sorry but even though your answer makes sense, since if the loop not runs then ofcourse nothing will be loaded, I am not sure how I would store the size of the vector in order for the elements of the vector to be loaded. – user3111197 May 17 '16 at 16:52
  • For start, perhaps [split loading and saving into separate methods](http://www.boost.org/doc/libs/1_61_0/libs/serialization/doc/tutorial.html#splitting). You would store the value of `v_any.size()` after the value of `seconds` and before you store the individual values. Then, when you're loading, you first read the size into a temporary value, and then iterate that many times to load the individual values and push them into the vector. You can see how it's implemented in [boost serialization code itself](http://www.boost.org/doc/libs/1_61_0/boost/serialization/vector.hpp). – Dan Mašek May 17 '16 at 17:08
  • Thanks a lot for your suggestion and links currently I made the following methods: – user3111197 May 17 '16 at 17:43
  • Better edit the question and add the code to the bottom as an update. It's unreadable in a comment. – Dan Mašek May 17 '16 at 17:48
  • Thanks a lot for your suggestion and links currently I made the following methods that you can see in the link below: https://codeshare.io/d4n5P Yet again I receive the following error: terminate called after throwing an instance of 'boost::exception_detail::clone_impl >' what(): boost::bad_any_cast: failed conversion using boost::any_cast – user3111197 May 17 '16 at 17:49
  • I see. You resize the vector, but that just fills the vector with default boost:any instances. Then you iterate over those elements, and try to use them (for example checking the type, casting them, etc) -- but they haven't been loaded yet... This is where things get tricky -- how do you know, before loading the element, its type? And to load it correctly, you need to know the type. So for each element, you need to store some kind of type information, followed by the actual value. – Dan Mašek May 17 '16 at 18:00
  • Thanks again for your answer, unfortunately I am really not sure what exactly to change in the code based on your suggestion. So in case it wouldn't be too much of asking to you, I would really appreciate if you would give me an example based on this instance how to do this. – user3111197 May 17 '16 at 18:09

0 Answers0