I have an abstract base class for a pointAccumulator. This abstract base will be filled out with methods such as a function that returns mean of all the points. An example of these two classes is shown below:
class lala {
public:
virtual someFunctions = 0;
virtual bool isEmpty() = 0;
};
class lalaLower : public lala {
public:
lalaLower(){}
~lalaLower(){}
someFunctions
template<class Archive> void serialize(Archive & ar, const unsigned int version) {
ar & heights_;
}
protected:
std::deque<double> heights_;
};
As you can see in the code I would also like to use boost serialization in to save these types. Now using a factory pattern i believe that you call the pointAccumulator types like this:
lala *a1 = new lalaLower();
My problem is that the templated serialize method will not be accessible if I call it this way. Also I cannot have the templated class in the abstract class as this is not allowed by c++. Is there a way to get around this?
Edit:
I have considered the non-intrusive method for serialization but that requires heights_ to be public which is not ideal, nor is it good programming style. I thought potentially a method using friend classes or functions could penetrate the class with access to the variables while still keeping the base class abstract? can anyone explain how this would work?
I think using friend classes or functions is a good solution, you could add new class like Serializor
here is a example of friend function
class Serializor;
class meanAccumulator : public pointAccumulator
{
public:
meanAccumulator(){}
~meanAccumulator(){}
double getHeight();
void addHeight(double Height);
void setHeight(double Height);
bool isEmpty(){ return heights_.empty(); }
protected: std::deque<double> heights_;
friend int Serializor::Func1( Serializor& );
};
refer to http://msdn.microsoft.com/en-us/library/ahhw8bzz.aspx
I believe you cannot do it without wrapping Archive
type parameter into polymorphic hierarchy this way or another.
It seems though that Boost.Serialization
does it for you.
As you may know that template
s and virtual
methods don't go hand in hand.
I would suggest to remove the meanAccumulator::serialize()
method and add into class pointAccumulator
body and call the virtual
functions inside wherever they are needed.
You can also think of passing a handle of derived class and call the method with that.
class pointAccumulator {
public:
template<class Archive, class Derived>
void serialize(Archive & ar, const unsigned int version, Derived &derived)
{ // optional ^^^^^^^^^^^^^^^^^
// call virtual methods to derived from here
// optional: for non-virtual method, you can use derived class handle
}
};
The only thing which you need to take care is that, whatever non-virtual methods you call inside serialize()
using derived
handle --> should be of same name in all the children classes from pointAccumulator
, irrespective of what they do inside.
In fact, I'll make my comment an answer:
~/src/snips$ cat serializer-demo.cc
#include <boost/archive/polymorphic_iarchive.hpp>
#include <boost/archive/polymorphic_oarchive.hpp>
typedef boost::archive::polymorphic_iarchive bpi;
typedef boost::archive::polymorphic_oarchive bpo;
typedef const unsigned int cui;
struct ABC
{
virtual void serialize(bpi &ar, cui v) = 0;
virtual void serialize(bpo &ar, cui v) = 0;
};
struct A : ABC
{
void serialize(bpi &ar, cui v ) { ar & data; }
void serialize(bpo &ar, cui v ) { ar & data; }
int data;
bool operator==(const A & rhs) const
{ return data == rhs.data; }
A(int data=0) : data(data) {}
};
#include <sstream>
#include <boost/archive/polymorphic_text_iarchive.hpp>
#include <boost/archive/polymorphic_text_oarchive.hpp>
#include <boost/archive/polymorphic_binary_iarchive.hpp>
#include <boost/archive/polymorphic_binary_oarchive.hpp>
int main(int argc, char* argv[])
{
const A a(1);
const ABC &abc = a;
A a1;
ABC &abc1 = a1;
{
std::stringstream ss;
{
boost::archive::polymorphic_text_oarchive oa(ss);
boost::archive::polymorphic_oarchive & oa_interface = oa;
oa_interface << abc;
}
{
boost::archive::polymorphic_text_iarchive ia(ss);
ia >> abc1;
}
}
if(! (a == a1))
return 1;
{
std::stringstream ss;
{
boost::archive::polymorphic_binary_oarchive oa(ss);
oa << abc;
}
{
boost::archive::polymorphic_binary_iarchive ia(ss);
boost::archive::polymorphic_iarchive & ia_interface = ia;
ia_interface >> abc1;
}
}
if(! (a == a1))
return 1;
return 0;
}
~/src/snips$ make -B serializer-demo
g++ -o bin/serializer-demo --std=c++0x -g -O -march=native -pipe -Wall -Wno-parentheses -lboost_serialization serializer-demo.cc
~/src/snips$ type -pa serializer-demo
./bin/serializer-demo
~/src/snips$ serializer-demo
~/src/snips$ echo $?
0
~/src/snips$
So I have an interesting way of faking virtualism for templated functions. Faking a virtual templated function c++
The basic motivation might be applied here if you need this enforced in the hierarchy, but you can utilize boost meta programming library to allow a run-time solution for this problem.