On Saturday, February 19, 2005 at 13:58:07 (-0600) Bill Lear writes:
I have a long question on how to combine a Singleton factory, serialization,
shared pointers and an object hierarchy half of which will be created
by a factory, and half of which will not.
Ok, this took so long to show up that I solved the problem, although
someone else may have a better solution.
Here is a (working) sketch of my solution, below my sig, if anyone is
interested.
Bill
#include <string>
#include <iostream>
#include <fstream>
#include <map>
using namespace std;
#include
#include
#include
#include
#include
#include
#include
#include
using namespace boost;
class Base {
public:
const string& key() const { return _key; }
virtual void foo() {
cout << "Base::foo(): key is [" << key() << "]\n";
}
virtual ~Base() { cout << "~iDataSTream()\n"; }
protected:
Base(const string& key = "") : _key(key) {
}
private:
string _key;
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive& ar, const unsigned int) {
ar & BOOST_SERIALIZATION_NVP(_key);
}
};
BOOST_CLASS_EXPORT(Base);
typedef shared_ptr<Base> BasePtrBase;
class Factory;
class BasePtr : public BasePtrBase {
public:
BasePtr() {}
BasePtr(const BasePtr& p) : BasePtrBase(p) {}
BasePtr(Base* p) : BasePtrBase(p) {}
private:
friend class boost::serialization::access;
template <class Archive>
void BasePtr::save(Archive& ar, unsigned int) const {
Base* my_ds = get();
bool flag = my_ds->key().size() != 0;
ar << BOOST_SERIALIZATION_NVP(flag);
if (flag) {
string key = my_ds->key();
ar << BOOST_SERIALIZATION_NVP(key);
} else {
ar << BOOST_SERIALIZATION_NVP(my_ds);
}
}
template <class Archive>
void BasePtr::load(Archive& ar, unsigned int) {
bool flag;
ar >> BOOST_SERIALIZATION_NVP(flag);
Base* my_ds;
if (flag) {
string key;
ar >> BOOST_SERIALIZATION_NVP(key);
*this = Factory::create(key);
} else {
ar >> BOOST_SERIALIZATION_NVP(my_ds);
*this = BasePtr(my_ds);
}
}
BOOST_SERIALIZATION_SPLIT_MEMBER()
};
BOOST_SHARED_POINTER_EXPORT(BasePtr);
class Derived : public Base {
public:
virtual void foo() {
cout << "Derived::foo(): key is [" << key() << "]\n";
}
virtual ~Derived() { cout << "~Derived()\n"; }
static BasePtr alloc(string key) {
return BasePtr(new Derived(key));
}
private:
Derived(const string& key) : Base(key) {}
};
class DerivedII : public Base {
public:
virtual void foo() {
cout << "DerivedII::foo(): key is [" << key() << "]\n";
}
virtual ~DerivedII() { cout << "~DerivedII()\n"; }
static BasePtr alloc(const string& key) {
return BasePtr(new DerivedII(key));
}
private:
DerivedII(const string& key) : Base(key) {}
};
class DerivedTest : public Base {
public:
virtual void foo() {
cout << "DerivedTest::foo(): key is [" << key() << "]\n";
}
virtual ~DerivedTest() { cout << "~DerivedTest()\n"; }
static BasePtr alloc() {
return BasePtr(new DerivedTest);
}
private:
DerivedTest() {}
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive& ar, const unsigned int) {
ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base);
}
};
BOOST_CLASS_EXPORT(DerivedTest);
typedef map BaseMap;
class Factory {
public:
static BasePtr create(string key) {
BaseMap::iterator i = ds_map.find(key);
if (i != ds_map.end()) {
return i->second;
}
BasePtr p;
if (key == "I") {
p = Derived::alloc(key);
} else {
p = DerivedII::alloc(key);
}
ds_map[key] = p;
return p;
}
private:
static BaseMap ds_map;
};
BaseMap Factory::ds_map;
BasePtr doit() {
{
BasePtr production(Factory::create("I"));
BasePtr productionII(Factory::create("II"));
BasePtr test(DerivedTest::alloc());
ofstream out("srl.xml");
archive::xml_oarchive oa(out);
oa & BOOST_SERIALIZATION_NVP(production);
oa & BOOST_SERIALIZATION_NVP(test);
oa & BOOST_SERIALIZATION_NVP(productionII);
}
BasePtr ds1;
BasePtr ds2;
BasePtr ds3;
{
ifstream in("srl.xml");
archive::xml_iarchive ia(in);
ia & BOOST_SERIALIZATION_NVP(ds1);
ia & BOOST_SERIALIZATION_NVP(ds2);
ia & BOOST_SERIALIZATION_NVP(ds3);
ds1->foo();
ds2->foo();
ds3->foo();
{
BasePtr dsA = ds1;
dsA->foo();
BasePtr dsB = ds1;
dsB->foo();
BasePtr dsC = ds1;
dsC->foo();
}
}
return ds1;
}
int main() {
{
BasePtr ds = doit();
cout << "In main:\n";
ds->foo();
cout << "done with main scope\n";
}
cout << "After main scope\n";
}