Boost serialization

Pages: 1234
Yea the .save and .load works but unfortunately not for my use case. I'd like to save everything (including the class example above and other standard data types) into one binary file. I tried to use the non-intrusive way from the tutorial but have been getting errors for the last two days:

Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
    #include <iostream>
    #include <fstream>
    #include <boost/archive/tmpdir.hpp>
    #include <boost/archive/binary_oarchive.hpp>
    #include <boost/archive/binary_iarchive.hpp>
    #include <armadillo>

    namespace boost {
    namespace serialization {

    template<class Archive>
    void serialize(Archive & ar, arma::mat &m, const unsigned int version)
    {

        ar & m.n_cols;          
        ar & m.n_rows;          
        ar & m.n_elem;                      


    }

      }
      }


    int main() {


  arma::mat A = arma::randu<arma::mat>(4,5);

  std::ofstream outputStream;
  outputStream.open("bin.dat");
  std::ostringstream oss;
  boost::archive::binary_oarchive oa(outputStream);
  oa & A;
  outputStream.close();

  arma::mat b; //tried also arma::mat b(4,5);
  std::ifstream inputStream;
  inputStream.open("bin.dat", std::ifstream::in);
  boost::archive::binary_iarchive ia(inputStream);
  ia & b;


      return 0;
    }




Errors:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
In file included from /usr/include/boost/archive/basic_text_oprimitive.hpp:34:0,
                 from /usr/include/boost/archive/text_oarchive.hpp:30,
                 from arma_boost.cpp:3:
/usr/include/boost/archive/detail/check.hpp: In instantiation of ‘void boost::archive::detail::check_const_loading() [with T = const unsigned int]’:
/usr/include/boost/archive/detail/iserializer.hpp:577:38:   required from ‘void boost::archive::load(Archive&, T&) [with Archive = boost::archive::binary_iarchive; T = const unsigned int]’
/usr/include/boost/archive/detail/common_iarchive.hpp:66:40:   required from ‘void boost::archive::detail::common_iarchive<Archive>::load_override(T&, int) [with T = const unsigned int; Archive = boost::archive::binary_iarchive]’
/usr/include/boost/archive/basic_binary_iarchive.hpp:70:7:   required from ‘void boost::archive::basic_binary_iarchive<Archive>::load_override(T&, int) [with T = const unsigned int; Archive = boost::archive::binary_iarchive]’
/usr/include/boost/archive/binary_iarchive_impl.hpp:50:9:   required from ‘void boost::archive::binary_iarchive_impl<Archive, Elem, Tr>::load_override(T&, int) [with T = const unsigned int; Archive = boost::archive::binary_iarchive; Elem = char; Tr = std::char_traits<char>]’
/usr/include/boost/archive/detail/interface_iarchive.hpp:60:9:   required from ‘Archive& boost::archive::detail::interface_iarchive<Archive>::operator>>(T&) [with T = const unsigned int; Archive = boost::archive::binary_iarchive]’
/usr/include/boost/archive/detail/interface_iarchive.hpp:67:32:   [ skipping 8 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/include/boost/archive/detail/common_iarchive.hpp:66:40:   required from ‘void boost::archive::detail::common_iarchive<Archive>::load_override(T&, int) [with T = arma::Mat<double>; Archive = boost::archive::binary_iarchive]’
/usr/include/boost/archive/basic_binary_iarchive.hpp:70:7:   required from ‘void boost::archive::basic_binary_iarchive<Archive>::load_override(T&, int) [with T = arma::Mat<double>; Archive = boost::archive::binary_iarchive]’
/usr/include/boost/archive/binary_iarchive_impl.hpp:50:9:   required from ‘void boost::archive::binary_iarchive_impl<Archive, Elem, Tr>::load_override(T&, int) [with T = arma::Mat<double>; Archive = boost::archive::binary_iarchive; Elem = char; Tr = std::char_traits<char>]’
/usr/include/boost/archive/detail/interface_iarchive.hpp:60:9:   required from ‘Archive& boost::archive::detail::interface_iarchive<Archive>::operator>>(T&) [with T = arma::Mat<double>; Archive = boost::archive::binary_iarchive]’
/usr/include/boost/archive/detail/interface_iarchive.hpp:67:32:   required from ‘Archive& boost::archive::detail::interface_iarchive<Archive>::operator&(T&) [with T = arma::Mat<double>; Archive = boost::archive::binary_iarchive]’
arma_boost.cpp:54:8:   required from here
/usr/include/boost/archive/detail/check.hpp:162:5: error: static assertion failed: typex::value
     BOOST_STATIC_ASSERT(typex::value);
     ^
In file included from /usr/include/boost/archive/binary_iarchive_impl.hpp:21:0,
                 from /usr/include/boost/archive/binary_iarchive.hpp:20,
                 from arma_boost.cpp:11:
/usr/include/boost/archive/basic_binary_iprimitive.hpp: In instantiation of ‘void boost::archive::basic_binary_iprimitive<Archive, Elem, Tr>::load(T&) [with T = const unsigned int; Archive = boost::archive::binary_iarchive; Elem = char; Tr = std::char_traits<char>]’:
/usr/include/boost/archive/detail/iserializer.hpp:107:9:   required from ‘static void boost::archive::load_access::load_primitive(Archive&, T&) [with Archive = boost::archive::binary_iarchive; T = const unsigned int]’
/usr/include/boost/archive/detail/iserializer.hpp:362:46:   required from ‘static void boost::archive::detail::load_non_pointer_type<Archive>::load_primitive::invoke(Archive&, T&) [with T = const unsigned int; Archive = boost::archive::binary_iarchive]’
/usr/include/boost/archive/detail/iserializer.hpp:439:28:   required from ‘static void boost::archive::detail::load_non_pointer_type<Archive>::invoke(Archive&, T&) [with T = const unsigned int; Archive = boost::archive::binary_iarchive]’
/usr/include/boost/archive/detail/iserializer.hpp:592:24:   required from ‘void boost::archive::load(Archive&, T&) [with Archive = boost::archive::binary_iarchive; T = const unsigned int]’
/usr/include/boost/archive/detail/common_iarchive.hpp:66:40:   required from ‘void boost::archive::detail::common_iarchive<Archive>::load_override(T&, int) [with T = const unsigned int; Archive = boost::archive::binary_iarchive]’
/usr/include/boost/archive/basic_binary_iarchive.hpp:70:7:   [ skipping 11 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/include/boost/archive/detail/common_iarchive.hpp:66:40:   required from ‘void boost::archive::detail::common_iarchive<Archive>::load_override(T&, int) [with T = arma::Mat<double>; Archive = boost::archive::binary_iarchive]’
/usr/include/boost/archive/basic_binary_iarchive.hpp:70:7:   required from ‘void boost::archive::basic_binary_iarchive<Archive>::load_override(T&, int) [with T = arma::Mat<double>; Archive = boost::archive::binary_iarchive]’
/usr/include/boost/archive/binary_iarchive_impl.hpp:50:9:   required from ‘void boost::archive::binary_iarchive_impl<Archive, Elem, Tr>::load_override(T&, int) [with T = arma::Mat<double>; Archive = boost::archive::binary_iarchive; Elem = char; Tr = std::char_traits<char>]’
/usr/include/boost/archive/detail/interface_iarchive.hpp:60:9:   required from ‘Archive& boost::archive::detail::interface_iarchive<Archive>::operator>>(T&) [with T = arma::Mat<double>; Archive = boost::archive::binary_iarchive]’
/usr/include/boost/archive/detail/interface_iarchive.hpp:67:32:   required from ‘Archive& boost::archive::detail::interface_iarchive<Archive>::operator&(T&) [with T = arma::Mat<double>; Archive = boost::archive::binary_iarchive]’
arma_boost.cpp:54:8:   required from here
/usr/include/boost/archive/basic_binary_iprimitive.hpp:88:35: error: invalid conversion from ‘const void*’ to ‘void*’ [-fpermissive]
         load_binary(& t, sizeof(T));
                                   ^
/usr/include/boost/archive/basic_binary_iprimitive.hpp:149:1: note: initializing argument 1 of ‘void boost::archive::basic_binary_iprimitive<Archive, Elem, Tr>::load_binary(void*, std::size_t) [with Archive = boost::archive::binary_iarchive; Elem = char; Tr = std::char_traits<char>; std::size_t = long unsigned int]’
 basic_binary_iprimitive<Archive, Elem, Tr>::load_binary(
 ^



Do you perhaps know where I am going wrong here?
Last edited on
n_{cols,rows,elems} are constant, you may save them to the file, but cannot load into them
don't have armadillo so cannot test it, but the idea would be something like
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// https://www.boost.org/doc/libs/1_47_0/libs/serialization/doc/serialization.html#splittingfreefunctions
BOOST_SERIALIZATION_SPLIT_FREE(arma::mat)


namespace boost { namespace serialization {
template<class Archive>
void save(Archive & ar, const arma::mat &t, unsigned int version)
{
	ar & t.n_rows;
	ar & t.n_cols;
	const double *data = t.memptr();
	for(int K=0; K<t.n_elem; ++K)
		ar & data[K];
}

template<class Archive>
void load(Archive & ar, arma::mat &t, unsigned int version)
{
	int rows, cols;
	ar & rows;
	ar & cols;
	t.set_size(rows, cols);
	double *data = t.memptr();
	for(int K=0; K<t.n_elem; ++K)
		ar & data[K];
}
}}
that should work for dense matrices
if you use sparse matrices, then check the interface to obtain the <row, col, value> tuple for each element and serialize that.
Thanks a ton ne555. I'm going to try this stuff out right now. Curious though, why does it matter that they are constants? That would make it very easy to save (already works as you said) and load, right? Is this the reason why my way with void serialize(Archive & ar, arma::mat &m, const unsigned int version) wouldn't work? I just followed the non-intrusive way in the tutorial and it should have worked. Again, apologies if this sounds like a "rtfm" question...I've read the tutorial and I've been googling and haven't found a reason for this.

Also, couldn't I just use

1
2
3
4
5
	ar & t.n_rows;
	ar & t.n_cols;
        double data[t.n_elem];
	for(int K=0; K<t.n_elem; ++K)
		ar & data[K];
?

If not, why would we need pointers to save the elements? Thanks again ne555!
> why does it matter that they are constants?
a constant cannot be modified
1
2
const int n = 42;
cin >> n; //error 



about your last code, ¿how is `data' related to your matrix?
now read http://arma.sourceforge.net/docs.html#memptr
«Obtain a raw pointer to the memory used for storing elements
Caveat: this function is not recommended for use unless you know what you are doing!»

if you are not comfortable with that, then check out the interface of arma::mat to see how to access individual elements
Hey ne555, been working on this since you last wrote. I'm trying to get everything under one roof so to speak. My end goal is to have everything in a class (matrices included) and serialize everything or certain aspects of the class. Everything works individually but when I try to add my arma code in the class at the beginning of our discussion, I get errors (primarily regarding the use of a namespace in a class -- from what I've read this is not allowed). Class Car has the arma code in it:

Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include <iostream>
#include <fstream>

#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <sstream>
#include <armadillo>
#include <boost/serialization/split_member.hpp>

BOOST_SERIALIZATION_SPLIT_FREE(arma::mat)

class Gear {
  public:
    template<typename Archive>
    void serialize(Archive& ar, unsigned int version) { ar & v; }

    void setV (const double& _v) { v = _v; }
    double getV () { return v; }

    void status () { std::cout << "v = " << v << std::endl; }

  private:
    double v;
};

class Car {
  public:
    template<typename Archive>
    void serialize(Archive& ar, unsigned int version) {
      ar & hp;
      ar & x;
    }

  namespace boost { 
  namespace serialization {

  template<class Archive>
  void save(Archive & ar, const arma::mat &t, unsigned int version)
  {
	ar & t.n_rows;
	ar & t.n_cols;
	const double *data = t.memptr();
	for(int K=0; K<t.n_elem; ++K)
		ar & data[K];
  }

  template<class Archive>
  void load(Archive & ar, arma::mat &t, unsigned int version)
  {
	int rows, cols;
	ar & rows;
	ar & cols;
	t.set_size(rows, cols);
	double *data = t.memptr();
	for(int K=0; K<t.n_elem; ++K)
		ar & data[K];
  }
  } }  
    
    arma::mat A;// = arma::randu<arma::mat>(4,5);

    void setHP (const int& _hp) { hp = _hp; }
    void setGear (Gear* _Gear) { x = _Gear; }
    void status () { std::cout << "hp = " << hp << " Gear with v = " << x->getV() << A<< std::endl; }

  private:
    int hp;
    Gear *x;
};

int main() {
  // Define new Gear:
  Gear* g = new Gear();
  g->setV(2.5);
  g->status();

  // Expectation is Car sets up the Gear.
  Car c;
  c.setHP(80);
  c.setGear(g);
  c.A = arma::randu<arma::mat>(4,5);
  //c.status();
  



  std::ofstream outputStream;
  outputStream.open("bin.dat");
  std::ostringstream oss;
  boost::archive::binary_oarchive oa(outputStream);
  oa & c;
  outputStream.close();

  Car b;
  std::ifstream inputStream;
  inputStream.open("bin.dat", std::ifstream::in);
  boost::archive::binary_iarchive ia(inputStream);
  ia & b;
  b.status();
  return 0;


}



Any thoughts on how I can make this work?
Last edited on
I suppose my main question is:

In the docs here:
https://www.boost.org/doc/libs/1_47_0/libs/serialization/doc/serialization.html#splittingfreefunctions

Why do we need namespaces in the first place? Could there be a work around for splitting functions without using namespaces?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
//free functions, outside the class
//serialization of arma::mat
namespace boost {
namespace serialization {

template <class Archive>
void save(Archive &ar, const arma::mat &t, unsigned int version) {
  ar & t.n_rows;
  ar & t.n_cols;
  const double *data = t.memptr();
  for (int K = 0; K < t.n_elem; ++K)
    ar & data[K];
}

template <class Archive>
void load(Archive &ar, arma::mat &t, unsigned int version) {
  int rows, cols;
  ar & rows;
  ar & cols;
  t.set_size(rows, cols);
  double *data = t.memptr();
  for (int K = 0; K < t.n_elem; ++K)
    ar & data[K];
}
} // namespace serialization
} // namespace boost
//special macro to make it work
BOOST_SERIALIZATION_SPLIT_FREE(arma::mat)


class Car {
  public:
    template<typename Archive>
    void serialize(Archive& ar, unsigned int version) {
      ar & hp;
      ar & x;

	  ar & A; //now you can use this to i/o your matrix
    }


    arma::mat A;// = arma::randu<arma::mat>(4,5);

    void setHP (const int& _hp) { hp = _hp; }
    void setGear (Gear* _Gear) { x = _Gear; }
    void status () { std::cout << "hp = " << hp << " Gear with v = " << x->getV() << A<< std::endl; }

  private:
    int hp;
    Gear *x;
};
Ah thanks ne555! I forgot to update my post but I figured it out about an hour ago and it's exactly what you have here. Makes sense that the namespaces should not be within the Car class as it has nothing to do with the Car class.
I am trying to do the same as above but with arma::vec. The code compiles but the post serialization vector doesn't have the same values as the initial vector. Here is the code:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <iostream>
#include <fstream>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <armadillo>
#include <boost/serialization/split_member.hpp>

//BOOST_SERIALIZATION_SPLIT_FREE(arma::sp_mat)
BOOST_SERIALIZATION_SPLIT_FREE(arma::vec)


namespace boost { 
namespace serialization {

template<class Archive>
void save(Archive & ar, const arma::vec &t, unsigned int version)
{
    // ar & t.n_rows;
    // ar & t.n_cols;
    ar & t.n_elem;
    const double *data = t.colptr(0);
    for(int K=0; K<t.n_elem; ++K)
	ar & data[K];

}

template<class Archive>
void load(Archive & ar, arma::vec &t, unsigned int version)
{
    // int rows, cols;
    int nelem;
    ar & nelem;
    // ar & rows;
    // ar & cols;
    t.set_size(nelem);
    double *data = t.colptr(0);
    for(int K=0; K<t.n_elem; ++K)
	ar & data[K];}
}}



arma::vec valuesFromSpMat (const arma::sp_mat& X)
{
      arma::vec out(X.n_nonzero);  
      arma::sp_mat::const_iterator start = X.begin();
      arma::sp_mat::const_iterator end   = X.end();  
      unsigned int k = 0;
      for(arma::sp_mat::const_iterator it = start; it != end; ++it) 
      {
        out(k) = (*it);
        k += 1;
      }
      return out;


}
int main() {

  arma::mat A(3,3, arma::fill::randu);
  A(1,1) = 0;
  A(1,2) = 0;
  A(0,0) = 0;
  A(2,1) = 0;
  A(2,0) = 0;
  arma::sp_mat B = arma::sp_mat(A);

  arma::vec C = valuesFromSpMat(B);

  std::ofstream outputStream;
  outputStream.open("bin.dat");
  //std::ostringstream oss;
  boost::archive::binary_oarchive oa(outputStream);
  oa & C;
  std::cout<<C<<std::endl;
  outputStream.close();

  arma::vec D;
  std::ifstream inputStream;
  inputStream.open("bin.dat", std::ifstream::in);
  boost::archive::binary_iarchive ia(inputStream);
  ia & D;
  std::cout<<D<<std::endl;
  return 0;
}




And the result of the two vectors:


1
2
3
4
5
6
7
8
9
10
11

   0.2505
   0.9467
   0.2513
   0.5206

  -2.1960e-68
   3.9793e+27
   5.5092e+97
  -2.3564e+97
Last edited on
Line 37 in load():
 
for(int K=0; K<t.n_elem; ++K)

Should be:
 
for(int K=0; K<nelem; ++K)


Here's the whole thing:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <armadillo>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/split_member.hpp>
#include <iostream>
#include <fstream>

BOOST_SERIALIZATION_SPLIT_FREE(arma::vec)

namespace boost { namespace serialization {
    template<class Archive>
    void save(Archive & ar, const arma::vec &t, unsigned int version) {
        ar << t.n_elem;
        auto data = t.colptr(0);
        for (size_t K = 0; K < t.n_elem; ++K)
            ar << data[K];
    }

    template<class Archive>
    void load(Archive & ar, arma::vec &t, unsigned int version) {
        size_t n_elem;
        ar >> n_elem;
        t.set_size(n_elem);
        t.zeros();
        auto data = t.colptr(0);
        for (size_t K = 0; K < n_elem; ++K)
            ar >> data[K];
    }
}} // serialization

arma::vec valuesFromSpMat (const arma::sp_mat& X) {
    arma::vec out(X.n_nonzero);  

    unsigned int k = 0;
    for(auto it = X.begin(); it != X.end(); ++it, k++) 
        out(k) = (*it);

    return out;
}

int main() {
    arma::mat A(3, 3, arma::fill::randu);
    A(1,1) = 0;
    A(1,2) = 0;
    A(0,0) = 0;
    A(2,1) = 0;
    A(2,0) = 0;
    arma::sp_mat B = arma::sp_mat(A);

    {
        arma::vec C = valuesFromSpMat(B);
        std::ofstream outputStream("bin.dat", std::ios::binary);
        boost::archive::binary_oarchive oa(outputStream);
        oa << C;
        std::cout << C << std::endl;
    }
    {
        arma::vec D;
        std::ifstream inputStream("bin.dat", std::ios::binary);
        boost::archive::binary_iarchive ia(inputStream);
        ia >> D;
        std::cout << D <<std::endl;
    }
}
Thanks a ton kbw! I changed my load() to what you have and it works. I have a few questions so I can fully understand your adjustments:

1. why use auto in line 14?
2. what's the purpose of t.zeros? I tried the code without t.zeros and it still works.
3. Outside of changing K<n_elem to K<nelem, the problem with the code was using int rather than size_t. Could you perhaps explain why with size_t it was able to work?

Thanks again!
Last edited on
I've modified my structs to include the serialize() function and tried using the same technique used in the tutorial for files with my socket
1. why use auto in line 14?
You don't really care what type it is do you? The code should be fine for any numeric type, so ... auto.

2. what's the purpose of t.zeros? I tried the code without t.zeros and it still works.
The array size is set without initializing the values. As these are a floating point type, they could be nan or some other weirdness, so I initialise them. But as you noted, you don't need to as we set them in the following lines.

3. Outside of changing K<n_elem to K<nelem, the problem with the code was using int rather than size_t. Could you perhaps explain why with size_t it was able to work?
Array ranges are related the to size of the range, and can't be negative. The standard type for that sort of thing is size_t.

I've never used boost serialize before (I'm not a fan of boost), and had to learn it tp fix your code, so there may be hidden errors.
1. why use auto in line 14?
auto tells the compiler to use the proper type for the iteration variable. Easier the compiler does the work instead of the programmer trying to type it correctly.
Thanks guys for the clarification. I have another addendum to the code where I want to add an abstract class. Essentially, there is an abstract base class with derived classes (expected to have many more than example below) whose attributes I would like to serialize. The thing is, the derived classes will have different attributes. That means the serialization of the derived classes will be different. I am having a few errors come up (see error results on the second post -- reached maximal post length):


Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include <iostream>
#include <memory>
#include <armadillo>
#include <vector>
#include <boost/serialization/split_member.hpp>
#include <armadillo>
#include <fstream>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <sstream>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/assume_abstract.hpp>



using namespace std;


BOOST_SERIALIZATION_ASSUME_ABSTRACT(Car); //Tell Boost that Car is abstract

//Serialization for Armadillo Matrices------------------
BOOST_SERIALIZATION_SPLIT_FREE(arma::mat)

//namespace for the Arma matrices
  namespace boost { 
  namespace serialization {

  template<class Archive>
  void save(Archive & ar, const arma::mat &t, unsigned int version)
  {
    ar & t.n_rows;
    ar & t.n_cols;
    const double *data = t.memptr();
    for(int K=0; K<t.n_elem; ++K)
        ar & data[K];
  }

  template<class Archive>
  void load(Archive & ar, arma::mat &t, unsigned int version)
  {
    int rows, cols;
    ar & rows;
    ar & cols;
    t.set_size(rows, cols);
    double *data = t.memptr();
    for(int K=0; K<t.n_elem; ++K)
        ar & data[K];
  }
  } } 
//----------------------------------------------
template<class Archive> 
class Car {
      public:
      int x;
      virtual double getInfo() = 0; 
      //template<typename Archive> 
      virtual void serialize(Archive& ar, unsigned int version) = 0;
      
};
template<class Archive>
class Porsche : public Car<class Archive>
{
      public:
          string owner;
          int hp;    
          arma::mat A;    
          double getInfo() {};
          //template<class Archive>
          void serialize(Archive& ar, unsigned int version) {
                  ar & hp;
                  ar & owner;
                  ar & getInfo();
    } 

};
template<class Archive>
class Audi : public Car<class Archive>
{
      public:
            string owner;
            int hp;    
            string second_owner;
            string country;    
            arma::mat A;    
            double getInfo() {};
            //template<typename Archive>
            void serialize(Archive& ar, unsigned int version) {
                  ar & hp;
                  ar & owner;
                  ar & second_owner;
                  ar & country;
                  ar & getInfo();
    }
};


int main () {  
    
  Audi<class Archive>* a = new Audi<class Archive>;
  Porsche<class Archive>* b = new Porsche<class Archive>;  
  a->getInfo();
  b->getInfo();  
  a->A = arma::randu<arma::mat>(4,5);
  b->A = arma::randu<arma::mat>(6,5);
  a->x = 20;
  b->x = 14;
  a->hp = 3;
  b->owner = "Joe";
  //a->serialize(); // Disregard
  //b->serialize();  

  std::ofstream outputStream;
  outputStream.open("bin.dat");
  std::ostringstream oss;
  boost::archive::binary_oarchive oa(outputStream);
  oa & a;
  oa & b;
//   vector<Car*> carsSave = {a, b};  // Trying to make for loop instead of writing 
//   for (auto & element : carsSave) {  // oa & c for every class. Didn't work as of yet,
//         oa & element; // errors.
//   }
  outputStream.close();

  Audi<class Archive>* c = new Audi<class Archive>;
  Porsche<class Archive>* d = new Porsche<class Archive>;
  std::ifstream inputStream;
  inputStream.open("bin.dat", std::ifstream::in);
  boost::archive::binary_iarchive ia(inputStream);
  ia & c;
  ia & d;
//   vector<Car*> carsLoad = {c, d};
//   for (auto & element : carsLoad) {
//         ia & element;
//   }
  return 0;

Last edited on
Errors need to be posted in two posts now. Too many characters:

Errors.1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

virtuell_funk_seri.cpp:57:34: error: using template type parameter ‘Archive’ after ‘classclass Porsche : public Car<class Archive>
                                  ^~~~~~~
virtuell_funk_seri.cpp:57:41: error: template argument 1 is invalid
 class Porsche : public Car<class Archive>
                                         ^
virtuell_funk_seri.cpp:73:31: error: using template type parameter ‘Archive’ after ‘classclass Audi : public Car<class Archive>
                               ^~~~~~~
virtuell_funk_seri.cpp:73:38: error: template argument 1 is invalid
 class Audi : public Car<class Archive>
                                      ^
virtuell_funk_seri.cpp: In function ‘int main()’:
virtuell_funk_seri.cpp:101:6: error: ‘class Audi<main()::Archive>’ has no member named ‘x’
   a->x = 20;
      ^
virtuell_funk_seri.cpp:102:6: error: ‘class Porsche<main()::Archive>’ has no member named ‘x’
   b->x = 14;
      ^
In file included from /usr/include/boost/serialization/split_member.hpp:23:0,
                 from virtuell_funk_seri.cpp:5:
/usr/include/boost/serialization/access.hpp: In instantiation of ‘static void boost::serialization::access::serialize(Archive&, T&, unsigned int) [with Archive = boost::archive::binary_oarchive; T = Audi<main()::Archive>]’:
/usr/include/boost/serialization/serialization.hpp:68:22:   required from ‘void boost::serialization::serialize(Archive&, T&, unsigned int) [with Archive = boost::archive::binary_oarchive; T = Audi<main()::Archive>]’
/usr/include/boost/serialization/serialization.hpp:126:14:   required from ‘void boost::serialization::serialize_adl(Archive&, T&, unsigned int) [with Archive = boost::archive::binary_oarchive; T = Audi<main()::Archive>]’
/usr/include/boost/archive/detail/oserializer.hpp:149:40:   required from ‘void boost::archive::detail::oserializer<Archive, T>::save_object_data(boost::archive::detail::basic_oarchive&, const void*) const [with Archive = boost::archive::binary_oarchive; T = Audi<main()::Archive>]’
/usr/include/boost/archive/detail/oserializer.hpp:102:1:   required from ‘class boost::archive::detail::oserializer<boost::archive::binary_oarchive, Audi<main()::Archive> >’
/usr/include/boost/archive/detail/oserializer.hpp:217:31:   required from ‘boost::archive::detail::pointer_oserializer<Archive, T>::pointer_oserializer() [with Archive = boost::archive::binary_oarchive; T = Audi<main()::Archive>]’
/usr/include/boost/serialization/singleton.hpp:100:7:   [ skipping 6 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/include/boost/archive/detail/common_oarchive.hpp:70:22:   required from ‘void boost::archive::detail::common_oarchive<Archive>::save_override(T&) [with T = Audi<main()::Archive>* const; Archive = boost::archive::binary_oarchive]’
/usr/include/boost/archive/basic_binary_oarchive.hpp:80:7:   required from ‘void boost::archive::basic_binary_oarchive<Archive>::save_override(const T&) [with T = Audi<main()::Archive>*; Archive = boost::archive::binary_oarchive]’
/usr/include/boost/archive/binary_oarchive_impl.hpp:59:9:   required from ‘void boost::archive::binary_oarchive_impl<Archive, Elem, Tr>::save_override(T&) [with T = Audi<main()::Archive>* const; Archive = boost::archive::binary_oarchive; Elem = char; Tr = std::char_traits<char>]’
/usr/include/boost/archive/detail/interface_oarchive.hpp:70:9:   required from ‘Archive& boost::archive::detail::interface_oarchive<Archive>::operator<<(const T&) [with T = Audi<main()::Archive>*; Archive = boost::archive::binary_oarchive]’
/usr/include/boost/archive/detail/interface_oarchive.hpp:77:32:   required from ‘Archive& boost::archive::detail::interface_oarchive<Archive>::operator&(const T&) [with T = Audi<main()::Archive>*; Archive = boost::archive::binary_oarchive]’
virtuell_funk_seri.cpp:112:8:   required from here
/usr/include/boost/serialization/access.hpp:116:9: error: no matching function for call to ‘Audi<main()::Archive>::serialize(boost::archive::binary_oarchive&, const unsigned int&)’
         t.serialize(ar, file_version);
         ^
virtuell_funk_seri.cpp:83:18: note: candidate: void Audi<Archive>::serialize(Archive&, unsigned int) [with Archive = main()::Archive]
             void serialize(Archive& ar, unsigned int version) {
                  ^~~~~~~~~
virtuell_funk_seri.cpp:83:18: note:   no known conversion for argument 1 from ‘boost::archive::binary_oarchive’ to ‘main()::Archive&’
In file included from /usr/include/boost/serialization/split_member.hpp:23:0,
                 from virtuell_funk_seri.cpp:5:
/usr/include/boost/serialization/access.hpp: In instantiation of ‘static void boost::serialization::access::serialize(Archive&, T&, unsigned int) [with Archive = boost::archive::binary_oarchive; T = Porsche<main()::Archive>]’:
/usr/include/boost/serialization/serialization.hpp:68:22:   required from ‘void boost::serialization::serialize(Archive&, T&, unsigned int) [with Archive = boost::archive::binary_oarchive; T = Porsche<main()::Archive>]’
/usr/include/boost/serialization/serialization.hpp:126:14:   required from ‘void boost::serialization::serialize_adl(Archive&, T&, unsigned int) [with Archive = boost::archive::binary_oarchive; T = Porsche<main()::Archive>]’
/usr/include/boost/archive/detail/oserializer.hpp:149:40:   required from ‘void boost::archive::detail::oserializer<Archive, T>::save_object_data(boost::archive::detail::basic_oarchive&, const void*) const [with Archive = boost::archive::binary_oarchive; T = Porsche<main()::Archive>]’
/usr/include/boost/archive/detail/oserializer.hpp:102:1:   required from ‘class boost::archive::detail::oserializer<boost::archive::binary_oarchive, Porsche<main()::Archive> >’
/usr/include/boost/archive/detail/oserializer.hpp:217:31:   required from ‘boost::archive::detail::pointer_oserializer<Archive, T>::pointer_oserializer() [with Archive = boost::archive::binary_oarchive; T = Porsche<main()::Archive>]’
/usr/include/boost/serialization/singleton.hpp:100:7:   [ skipping 6 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/include/boost/archive/detail/common_oarchive.hpp:70:22:   required from ‘void boost::archive::detail::common_oarchive<Archive>::save_override(T&) [with T = Porsche<main()::Archive>* const; Archive = boost::archive::binary_oarchive]’
/usr/include/boost/archive/basic_binary_oarchive.hpp:80:7:   required from ‘void boost::archive::basic_binary_oarchive<Archive>::save_override(const T&) [with T = Porsche<main()::Archive>*; Archive = boost::archive::binary_oarchive]’
/usr/include/boost/archive/binary_oarchive_impl.hpp:59:9:   required from ‘void boost::archive::binary_oarchive_impl<Archive, Elem, Tr>::save_override(T&) [with T = Porsche<main()::Archive>* const; Archive = boost::archive::binary_oarchive; Elem = char; Tr = std::char_traits<char>]’
/usr/include/boost/archive/detail/interface_oarchive.hpp:70:9:   required from ‘Archive& boost::archive::detail::interface_oarchive<Archive>::operator<<(const T&) [with T = Porsche<main()::Archive>*; Archive = boost::archive::binary_oarchive]’
/usr/include/boost/archive/detail/interface_oarchive.hpp:77:32:   required from ‘Archive& boost::archive::detail::interface_oarchive<Archive>::operator&(const T&) [with T = Porsche<main()::Archive>*; Archive = boost::archive::binary_oarchive]’
virtuell_funk_seri.cpp:113:8:   required from here
/usr/include/boost/serialization/access.hpp:116:9: error: no matching function for call to ‘Porsche<main()::Archive>::serialize(boost::archive::binary_oarchive&, const unsigned int&)’
         t.serialize(ar, file_version);
         ^
virtuell_funk_seri.cpp:65:16: note: candidate: void Porsche<Archive>::serialize(Archive&, unsigned int) [with Archive = main()::Archive]
           void serialize(Archive& ar, unsigned int version) {
                ^~~~~~~~~
Errors.2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

virtuell_funk_seri.cpp:65:16: note:   no known conversion for argument 1 from ‘boost::archive::binary_oarchive’ to ‘main()::Archive&’
In file included from /usr/include/boost/serialization/split_member.hpp:23:0,
                 from virtuell_funk_seri.cpp:5:
/usr/include/boost/serialization/access.hpp: In instantiation of ‘static void boost::serialization::access::serialize(Archive&, T&, unsigned int) [with Archive = boost::archive::binary_iarchive; T = Audi<main()::Archive>]’:
/usr/include/boost/serialization/serialization.hpp:68:22:   required from ‘void boost::serialization::serialize(Archive&, T&, unsigned int) [with Archive = boost::archive::binary_iarchive; T = Audi<main()::Archive>]’
/usr/include/boost/serialization/serialization.hpp:126:14:   required from ‘void boost::serialization::serialize_adl(Archive&, T&, unsigned int) [with Archive = boost::archive::binary_iarchive; T = Audi<main()::Archive>]’
/usr/include/boost/archive/detail/iserializer.hpp:188:40:   required from ‘void boost::archive::detail::iserializer<Archive, T>::load_object_data(boost::archive::detail::basic_iarchive&, void*, unsigned int) const [with Archive = boost::archive::binary_iarchive; T = Audi<main()::Archive>]’
/usr/include/boost/archive/detail/iserializer.hpp:120:1:   required from ‘class boost::archive::detail::iserializer<boost::archive::binary_iarchive, Audi<main()::Archive> >’
/usr/include/boost/archive/detail/iserializer.hpp:369:31:   required from ‘boost::archive::detail::pointer_iserializer<Archive, T>::pointer_iserializer() [with Archive = boost::archive::binary_iarchive; T = Audi<main()::Archive>]’
/usr/include/boost/serialization/singleton.hpp:100:7:   [ skipping 7 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/include/boost/archive/detail/common_iarchive.hpp:66:22:   required from ‘void boost::archive::detail::common_iarchive<Archive>::load_override(T&) [with T = Audi<main()::Archive>*; Archive = boost::archive::binary_iarchive]’
/usr/include/boost/archive/basic_binary_iarchive.hpp:75:7:   required from ‘void boost::archive::basic_binary_iarchive<Archive>::load_override(T&) [with T = Audi<main()::Archive>*; Archive = boost::archive::binary_iarchive]’
/usr/include/boost/archive/binary_iarchive_impl.hpp:58:9:   required from ‘void boost::archive::binary_iarchive_impl<Archive, Elem, Tr>::load_override(T&) [with T = Audi<main()::Archive>*; Archive = boost::archive::binary_iarchive; Elem = char; Tr = std::char_traits<char>]’
/usr/include/boost/archive/detail/interface_iarchive.hpp:68:9:   required from ‘Archive& boost::archive::detail::interface_iarchive<Archive>::operator>>(T&) [with T = Audi<main()::Archive>*; Archive = boost::archive::binary_iarchive]’
/usr/include/boost/archive/detail/interface_iarchive.hpp:75:32:   required from ‘Archive& boost::archive::detail::interface_iarchive<Archive>::operator&(T&) [with T = Audi<main()::Archive>*; Archive = boost::archive::binary_iarchive]’
virtuell_funk_seri.cpp:125:8:   required from here
/usr/include/boost/serialization/access.hpp:116:9: error: no matching function for call to ‘Audi<main()::Archive>::serialize(boost::archive::binary_iarchive&, const unsigned int&)’
         t.serialize(ar, file_version);
         ^
virtuell_funk_seri.cpp:83:18: note: candidate: void Audi<Archive>::serialize(Archive&, unsigned int) [with Archive = main()::Archive]
             void serialize(Archive& ar, unsigned int version) {
                  ^~~~~~~~~
virtuell_funk_seri.cpp:83:18: note:   no known conversion for argument 1 from ‘boost::archive::binary_iarchive’ to ‘main()::Archive&’
In file included from /usr/include/boost/serialization/split_member.hpp:23:0,
                 from virtuell_funk_seri.cpp:5:
/usr/include/boost/serialization/access.hpp: In instantiation of ‘static void boost::serialization::access::serialize(Archive&, T&, unsigned int) [with Archive = boost::archive::binary_iarchive; T = Porsche<main()::Archive>]’:
/usr/include/boost/serialization/serialization.hpp:68:22:   required from ‘void boost::serialization::serialize(Archive&, T&, unsigned int) [with Archive = boost::archive::binary_iarchive; T = Porsche<main()::Archive>]’
/usr/include/boost/serialization/serialization.hpp:126:14:   required from ‘void boost::serialization::serialize_adl(Archive&, T&, unsigned int) [with Archive = boost::archive::binary_iarchive; T = Porsche<main()::Archive>]’
/usr/include/boost/archive/detail/iserializer.hpp:188:40:   required from ‘void boost::archive::detail::iserializer<Archive, T>::load_object_data(boost::archive::detail::basic_iarchive&, void*, unsigned int) const [with Archive = boost::archive::binary_iarchive; T = Porsche<main()::Archive>]’
/usr/include/boost/archive/detail/iserializer.hpp:120:1:   required from ‘class boost::archive::detail::iserializer<boost::archive::binary_iarchive, Porsche<main()::Archive> >’
/usr/include/boost/archive/detail/iserializer.hpp:369:31:   required from ‘boost::archive::detail::pointer_iserializer<Archive, T>::pointer_iserializer() [with Archive = boost::archive::binary_iarchive; T = Porsche<main()::Archive>]’
/usr/include/boost/serialization/singleton.hpp:100:7:   [ skipping 7 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/include/boost/archive/detail/common_iarchive.hpp:66:22:   required from ‘void boost::archive::detail::common_iarchive<Archive>::load_override(T&) [with T = Porsche<main()::Archive>*; Archive = boost::archive::binary_iarchive]’
/usr/include/boost/archive/basic_binary_iarchive.hpp:75:7:   required from ‘void boost::archive::basic_binary_iarchive<Archive>::load_override(T&) [with T = Porsche<main()::Archive>*; Archive = boost::archive::binary_iarchive]’
/usr/include/boost/archive/binary_iarchive_impl.hpp:58:9:   required from ‘void boost::archive::binary_iarchive_impl<Archive, Elem, Tr>::load_override(T&) [with T = Porsche<main()::Archive>*; Archive = boost::archive::binary_iarchive; Elem = char; Tr = std::char_traits<char>]’
/usr/include/boost/archive/detail/interface_iarchive.hpp:68:9:   required from ‘Archive& boost::archive::detail::interface_iarchive<Archive>::operator>>(T&) [with T = Porsche<main()::Archive>*; Archive = boost::archive::binary_iarchive]’
/usr/include/boost/archive/detail/interface_iarchive.hpp:75:32:   required from ‘Archive& boost::archive::detail::interface_iarchive<Archive>::operator&(T&) [with T = Porsche<main()::Archive>*; Archive = boost::archive::binary_iarchive]’
virtuell_funk_seri.cpp:126:8:   required from here
/usr/include/boost/serialization/access.hpp:116:9: error: no matching function for call to ‘Porsche<main()::Archive>::serialize(boost::archive::binary_iarchive&, const unsigned int&)’
         t.serialize(ar, file_version);
         ^
virtuell_funk_seri.cpp:65:16: note: candidate: void Porsche<Archive>::serialize(Archive&, unsigned int) [with Archive = main()::Archive]
           void serialize(Archive& ar, unsigned int version) {
                ^~~~~~~~~
virtuell_funk_seri.cpp:65:16: note:   no known conversion for argument 1 from ‘boost::archive::binary_iarchive’ to ‘main()::Archive&’

You really should put new stuff in a new post.
I figured it runs with this topic and it would save spamming the forum. It also gives a bit of background what I've already tried.
class Porsche : public Car<class Archive>

should just be:

class Porsche : public Car<Archive>

Similarly, stuff like:

Audi<class Archive>* a = new Audi<class Archive>;

should just be:

Audi<Archive>* a = new Audi<Archive>;

Fix that, and see which other errors go away too.

Although I don't see any definition of Archive that can be seen by main. Or is that defined in boost?
Last edited on
Pages: 1234