
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 <boost/serialization/shared_ptr.hpp> #include <boost/serialization/utility.hpp> #include <boost/serialization/nvp.hpp> #include <boost/archive/xml_iarchive.hpp> #include <boost/archive/xml_oarchive.hpp> #include <boost/serialization/export.hpp> #include <boost/serialization/split_member.hpp> #include <boost/shared_ptr.hpp> 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<string, BasePtr> 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"; }