1

I am trying to serialize/deserialize an Armadillo colvec object using Boost. The colvec is a column vector with a few different sizes e.g. it can have 2 rows for 2d vector, 3 rows for 3d vector and I'm also using other specific vector sizes in the code.

I am not sure how to deal with the serialisation for the colvec type in boost when the number of rows in the colvec is unknown during deserialization.

For example to serialise, I might include the following:-

namespace boost
{
    namespace serialization
    {
        template<class Archive>
        void serialize(Archive& archive, colvec& vector, unsigned int)
        {
            for (int i=0; i<vector.size(); i++)
            {
                archive& vector[i];
            }
        }
    }
}

This will serialise a colvec with any number of rows. However, when this code is run during "de-serialization" vector will be a colvec of size()==0 e.g. the required number of rows will be unknown.

I was wondering what would be the best way to handle this.

I may be mistaken in my understanding. I am new to both Armadillo and Boost.

user3079907
  • 133
  • 1
  • 10
  • Yes, sorry but the colvec is an Armadillo typedef for the Mat class. I am not using std::vector in this example... – user3079907 Jun 30 '17 at 20:06
  • What is colvec? [`arma::Col`](https://stackoverflow.com/q/39890640/1460794)? – wally Jun 30 '17 at 20:18
  • yes, it is a typedef for Col which is derived from a Mat. – user3079907 Jun 30 '17 at 21:44
  • The issue seems to be (although I could be missing something) is that Boost Serialisation will call the default constructor for colvec and this will generate a Mat structure with 1 column. It would appear that the default constructor does not create rows for the colvec so it appears during de-serialization as a Mat with 1 column and 0 rows. Hence the deserialization fails. – user3079907 Jun 30 '17 at 21:58

1 Answers1

1

I would recommend to split apart load/save. For array you also need to store size first in order to be able to know how many components you will have to read when deserializing. For contiguous memory layout use the optimized

boost::serialization::make_array(T*,size)

function. Finally If you want to support XML archive use

boost::serialization::make_nvp(char*, T)
// or the BOOST_SERIALIZATION_NVP macro

You can have a look at

/usr/include/boost/serialization/vector.hpp

to see how Boost serializes std::vector, the code is easy to read.

I have never used Armadillo however unoptimized code (I have no clue about memory layout etc...) will certainly be close to:

template<class Archive>
inline void save(Archive & ar,const colvec& v,const unsigned int) {

    const size_t size = v.size();
    ar << BOOST_SERIALIZATION_NVP(size);

    for(size_t i=0;i<size;++i) {
        ar << boost::serialization::make_nvp("v_i",v[i]);
    }
}

template<class Archive>
inline void load(Archive & ar,colvec& v,const unsigned int) {

   size_t size;
   ar >> BOOST_SERIALIZATION_NVP(size);

   v.resize(size);

   for(size_t i=0;i<size;++i) {
        ar >> boost::serialization::make_nvp("v_i",v[i]);
    }
}

template<class Archive>
inline void serialize(Archive & ar,colvec& v,
                      const unsigned int file_version) {

 boost::serialization::split_free(ar, v, file_version);

}
Picaud Vincent
  • 10,518
  • 5
  • 31
  • 70
  • also look at http://www.boost.org/doc/libs/1_64_0/libs/serialization/doc/serialization.html#constructors – sehe Jul 01 '17 at 08:01
  • 1
    Thanks. This is perfect and worked without modification. The only other way I could think of was to wrap the colvec in a struct e.g. to have a struct "colvec2d" and another struct called "colvec3d" etc and to create different serialize methods for each. But this would be ugly and involve lots of code changes. Many thanks for your excellent answer. – user3079907 Jul 01 '17 at 11:15