////////////////////////////////////////////////////////////////// // // Object factory for GNU Gatekeeper // // Copyright (c) Citron Network Inc. 2003 // // This work is published under the GNU Public License (GPL) // see file COPYING for details. // We also explicitely grant the right to link this code // with the OpenH323 library. // // initial author: Chih-Wei Huang // initial version: 06/05/2003 // ////////////////////////////////////////////////////////////////// #ifndef FACTORY_H #define FACTORY_H "@(#) $Id: factory.h,v 1.7 2006/04/14 13:56:19 willamowius Exp $" /***************************************************************** // // An example how to use the factory template // // a base class for polymorphic objects class SampleBase { public: SampleBase() {} SampleBase(const char *n) { cerr << "This is a " << n << "\n"; } virtual ~SampleBase() {} template struct Init : public Factory::Creator0 { Init(const char *n) : Factory::Creator0(n), n_(n) {} virtual SampleBase *operator()() const { return new Derived(n_); } const char *n_; }; }; class SampleA : public SampleBase { public: SampleA(const char *n) : SampleBase(n) {} }; class SampleB : public SampleBase { public: SampleB(const char *n) : SampleBase(n) {} }; class SampleC : public SampleBase { public: SampleC(const char *n) : SampleBase(n) {} SampleC(int i) { cerr << "This is a SampleC " << i << "\n"; } // how to create object for a class with different constructors struct InitC : public SampleBase::Init, public Factory::Creator1 { InitC(const char *n) : SampleBase::Init(n), Factory::Creator1(n) {} virtual SampleBase *operator()(int i) const { return new SampleC(i); } }; }; // register the derived classes with the factory SampleA::Init SampleAInit("SampleA"); SampleB::Init SampleBInit("SampleB"); SampleC::InitC SampleCInit("SampleC"); void CreateSamples() { SampleBase *pa, *pb, *pc1, *pc2, *pc3; pa = Factory::Create("SampleA"); pb = Factory::Create("SampleB"); pc1 = Factory::Create("SampleC"); pc2 = Factory::Create("SampleC", 2); pc3 = Factory::Create("SampleC", 1, 2, 3); // runtime error } The output This is a SampleA This is a SampleB This is a SampleC This is a SampleC 2 and an error message in trace factory.h(135) Init Can't create SampleC with 3 parameter(s) *****************************************************************/ #if defined(_WIN32) && (_MSC_VER >= 1200) #pragma warning( disable : 4355 ) // warning about using 'this' in initializer #endif #include #include namespace std { // gcc 3.x said specialization can't be put in different namespace template<> struct less : public binary_function { bool operator()(const char *s1, const char *s2) const { return strcmp(s1, s2) < 0; } }; } // a function object template with returned value R template struct Functor { typedef R result_type; virtual ~Functor() {} }; // function objects with different parameters // currently at most 3 parameters are supported // since VC6 didn't support partial specialization, // we have to define Functor with different parameters to // different names template struct Functor0 : public Functor { virtual R operator()() const = 0; }; template struct Functor1 : public Functor { typedef T1 argument_type; virtual R operator()(T1) const = 0; }; template struct Functor2 : public Functor { typedef T1 first_argument_type; typedef T2 second_argument_type; virtual R operator()(T1, T2) const = 0; }; template struct Functor3 : public Functor { typedef T1 first_argument_type; typedef T2 second_argument_type; typedef T3 third_argument_type; virtual R operator()(T1, T2, T3) const = 0; }; // object factory template template class Factory { public: typedef Factory Self; typedef Functor *Creator; typedef std::map Associations; static Creator Register(Identifier n, Creator c); static void SetDefaultCreator(Creator c) { m_default = c; } // registrars class Registrar { protected: Identifier m_id; Creator m_old; #if defined(_WIN32) && (_MSC_VER <= 1300) Registrar(Identifier n, Creator c) : m_id(n) { m_old = Self::Register(n, c); } ~Registrar() { if (m_old) Self::Register(m_id, m_old); } #else Registrar(Identifier n, Creator c); ~Registrar(); #endif }; struct Creator0 : public Functor0, Registrar { Creator0(Identifier n) : Registrar(n, this) {} }; template struct Creator1 : public Functor1, Registrar { Creator1(Identifier n) : Registrar(n, this) {} }; template struct Creator2 : public Functor2, Registrar { Creator2(Identifier n) : Registrar(n, this) {} }; template struct Creator3 : public Functor3, Registrar { Creator3(Identifier n) : Registrar(n, this) {} }; static Product *Create(Identifier n) { Functor0 *f0; return FindCreator(n, 0, f0) ? (*f0)() : 0; } template static Product *Create(Identifier n, P1 p1) { Functor1 *f1; return FindCreator(n, 1, f1) ? (*f1)(p1) : 0; } template static Product *Create(Identifier n, P1 p1, P2 p2) { Functor2 *f2; return FindCreator(n, 2, f2) ? (*f2)(p1, p2) : 0; } template static Product *Create(Identifier n, P1 p1, P2 p2, P3 p3) { Functor3 *f3; return FindCreator(n, 3, f3) ? (*f3)(p1, p2, p3) : 0; } private: static Creator FindCreator(Identifier); static bool ParmMismatch(Identifier, int); template static bool FindCreator(Identifier n, int i, P & p) { Creator creator = FindCreator(n); p = dynamic_cast

(creator); return creator && (p || ParmMismatch(n, i)); } static Associations *m_associations; static Creator m_default; }; #if !defined(_WIN32) || (_MSC_VER > 1300) // stupid VC can't instantiate these template Factory::Registrar::Registrar(Identifier n, Creator c) : m_id(n) { // VS.NET fix #if defined(_WIN32) && (_MSC_VER > 1300) m_old = Register(n, c); #else m_old = Self::Register(n, c); #endif } template Factory::Registrar::~Registrar() { if (m_old) // VS.NET fix #if defined(_WIN32) && (_MSC_VER > 1300) Register(m_id, m_old); #else Self::Register(m_id, m_old); #endif } #endif template Functor *Factory::Register(Identifier n, Creator c) { static Associations associations; m_associations = &associations; Creator & d = associations[n]; Creator old = d; d = c; return old; } template Functor *Factory::FindCreator(Identifier n) { typename Associations::iterator i = m_associations->find(n); if (i != m_associations->end()) return i->second; else if (m_default) return m_default; PTRACE(1, "Init\tCan't create unknown class " << n); return 0; } template bool Factory::ParmMismatch(Identifier n, int i) { PTRACE(1, "Init\tCan't create " << n << " with " << i << " parameter(s)"); return false; } template std::map *> *Factory::m_associations; template Functor *Factory::m_default = 0; // a simple creator for classes having default constructor // the ConcreteProduct must define its base class as a subtype Base template struct SimpleCreator : public Factory::Creator0 { typedef typename ConcreteProduct::Base AbstractProduct; SimpleCreator(Identifier n) : Factory::Creator0(n) {} virtual AbstractProduct *operator()() const { return new ConcreteProduct; } }; #endif // FACTORY_H