Boost logo

Boost :

Subject: Re: [boost] Any interest in static plugins?
From: Jeremy Pack (rostovpack_at_[hidden])
Date: 2009-12-03 17:24:04


> Your example uses a centralized place (the type-map) to store the
> information about the derived classes/plugins. That is what I'm aiming to
> avoid with my static plugin library.
>
>
I did this because I figured it would be trivial for a user who wanted it
global to make it global. It is just like your "Factory Manager", but it can
be either global or local (with simple wrapper functions).

You could make it safe with the static initialization by making sure that
the Factory Manager is initialized before it is used. For your use case, I
think it would be sufficient to instantiate the Factory Manager inside of
the function that returns it (Get() below):

template <class Base>
class FactoryManager {
public:
  static void RegisterTypeConstructor(Base* (*func)(), const string& id) {
    Get()->insert(make_pair(id, func));
  }

  static map<string, Base*(*)()>* Get() {
    static map<string, Base*(*)()> constructors;
    return &constructors;
  }

  static Base* Create(const string& id) {
    return (*(*Get())[id])();
  }
};

template <class Derived, class Base>
class Factory {
public:
  Factory(const string& name) {
    FactoryManager<Base>::RegisterTypeConstructor(&Factory::Create, name);
  }

  static Base* Create() {
    return new Derived();
  }
};

class MyBaseClass {
public:
  virtual void PrintString() {
    cout << "MyBaseClass" << endl;
  }
};

class MyDerivedClass : public MyBaseClass {
public:
  virtual void PrintString() {
    cout << "MyDerivedClass" << endl;
  }
};

Factory<MyDerivedClass, MyBaseClass> i("derived");

class MyOtherDerivedClass : public MyBaseClass {
public:
  virtual void PrintString() {
    cout << "MyOtherDerivedClass" << endl;
  }
};

Factory<MyOtherDerivedClass, MyBaseClass> j("other_derived");

int main(int argc, char* argv[]) {
  cout << "Entering main." << endl;
  MyBaseClass* c = FactoryManager<MyBaseClass>::Create("derived");
  MyBaseClass* d = FactoryManager<MyBaseClass>::Create("other_derived");
  c->PrintString();
  d->PrintString();
}
/// End of code

Jeremy


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk