I have spent several hours combing the documentation and archives, but
can't seem to find an answer to my problem.
I have an abstract base class, Operation with a pure virtual function
'double value() = 0'. I derive a class, BinaryOperation from
Operation. It takes as arguments an operation type (+, -, *, /) and
two Operation pointers --- one for the left operand, one for the
right. It stores these two pointers internally and uses them when the
value() method is invoked.
I derive two more classes from Operation, trivial, made-up, useless
ones. One is called IncrementOperation, one is called
DecrementOperation.
I can save to an XML archive properly, but when I try to restore, it
core dumps. I am running gcc-3.2. I have tried everything I can
think of, but am stuck. I have tried using polymorphic_xml_iarchive
(and corresponding output version), but it still fails.
The first few stack frames from GDB are:
#0 0x0808897f in ?? ()
#1 0x08052f7d in boost::archive::detail::basic_iarchive::load_pointer(void*&, boost::archive::detail::basic_pointer_iserializer const*, boost::archive::detail::basic_pointer_iserializer const* (*)(boost::serialization::extended_type_info const&)) ()
#2 0x0804c78a in boost::archive::detail::load_pointer_type::invoke(boost::archive::xml_iarchive&, Operation*&) (
ar=@0xbffff0e0, t=@0xbffff330)
at /usr/local/include/boost-1_32/boost/archive/detail/iserializer.hpp:450
#3 0x0804c51a in load (
ar=@0xbffff0e0, t=@0xbffff330)
at /usr/local/include/boost-1_32/boost/archive/detail/iserializer.hpp:529
Following my sig, I've posted the xml input file that is generated by
the save, and then following that, the C++ code (fairly short). It is
failing on the following line:
ia & BOOST_SERIALIZATION_NVP(t);
Any help would be appreciated.
Thanks.
Bill
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE boost_serialization>
<t class_id="1" class_name="BinaryOperation" tracking_level="1" version="0" object_id="_0">
<Operation class_id="0" tracking_level="1" version="0" object_id="_1"></Operation>
<_op>42
<_left_operand class_id_reference="1" object_id="_2">
<Operation object_id="_3"></Operation>
<_op>43
<_left_operand class_id="2" class_name="IncrementOperation" tracking_level="1" version="0" object_id="_4">
<Operation object_id="_5"></Operation>
<_init>33
<_right_operand class_id="3" class_name="DecrementOperation" tracking_level="1" version="0" object_id="_6">
<Operation object_id="_7"></Operation>
<_init>333
<_right_operand class_id_reference="1" object_id="_8">
<Operation object_id="_9"></Operation>
<_op>45
<_left_operand class_id_reference="3" object_id="_10">
<Operation object_id="_11"></Operation>
<_init>444
<_right_operand class_id_reference="2" object_id="_12">
<Operation object_id="_13"></Operation>
<_init>44
</t>
#include <string>
#include <iomanip>
#include <iostream>
#include <fstream>
#include <stdexcept>
#include
#include
#include
//#include
//#include
#include
class Operation {
public:
Operation() { }
virtual ~Operation() { }
virtual double value() = 0;
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int /* file_version */){
}
};
BOOST_IS_ABSTRACT(Operation);
class BinaryOperation: public Operation {
public:
BinaryOperation() : _op(' '), _left_operand(0), _right_operand(0) { }
BinaryOperation(char op, Operation* left_operand, Operation* right_operand)
: _op(op), _left_operand(left_operand), _right_operand(right_operand) {
}
virtual ~BinaryOperation() { }
virtual double value() {
switch (_op) {
case '+':
return _left_operand->value() + _right_operand->value(); break;
case '-':
return _left_operand->value() - _right_operand->value(); break;
case '*':
return _left_operand->value() * _right_operand->value(); break;
case '/':
return _left_operand->value() / _right_operand->value(); break;
}
}
protected:
char _op;
Operation* _left_operand;
Operation* _right_operand;
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int /* file_version */){
ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Operation)
& BOOST_SERIALIZATION_NVP(_op)
& BOOST_SERIALIZATION_NVP(_left_operand)
& BOOST_SERIALIZATION_NVP(_right_operand);
}
};
BOOST_CLASS_EXPORT_GUID(BinaryOperation, "BinaryOperation");
class IncrementOperation : public Operation {
public:
IncrementOperation() : _init(0) {
}
IncrementOperation(double init) : _init(init) {
}
virtual double value() {
return _init++;
}
protected:
double _init;
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int /* file_version */){
ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Operation)
& BOOST_SERIALIZATION_NVP(_init);
}
};
BOOST_CLASS_EXPORT_GUID(IncrementOperation, "IncrementOperation");
class DecrementOperation : public Operation {
public:
DecrementOperation() : _init(0) {
}
DecrementOperation(double init) : _init(init) {
}
virtual double value() {
return _init--;
}
protected:
double _init;
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int /* file_version */){
ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Operation)
& BOOST_SERIALIZATION_NVP(_init);
}
};
BOOST_CLASS_EXPORT_GUID(DecrementOperation, "DecrementOperation");
void save_Operation(const Operation* t) {
std::ofstream ofs("operation.xml");
assert(ofs.good());
boost::archive::xml_oarchive oa(ofs);
//boost::archive::polymorphic_xml_oarchive oa(ofs);
oa & BOOST_SERIALIZATION_NVP(t);
}
void restore_Operation(Operation*& t) {
std::ifstream ifs("operation.xml");
if (!ifs.good()) {
throw std::runtime_error("No input archive file");
}
boost::archive::xml_iarchive ia(ifs);
//boost::archive::polymorphic_xml_iarchive ia(ifs);
std::cout << "Reading ...\n";
ia & BOOST_SERIALIZATION_NVP(t);
std::cout << "Done reading ...\n";
}
int main(int, char *[]) {
try {
Operation* a = new BinaryOperation('+',
new IncrementOperation(33),
new DecrementOperation(333));
Operation* b = new BinaryOperation('-',
new DecrementOperation(444),
new IncrementOperation(44));
Operation* c = new BinaryOperation('*', a, b);
save_Operation(c);
Operation* new_c;
std::cout << "Restoring\n";
restore_Operation(new_c);
} catch (std::exception e) {
std::cerr << e.what() << '\n';
return 1;
}
return 0;
}