/*
 * $Id$
 *
 * Created: 27.2.2007
 * Author: jedi
 *
 * Loki introduces a generic object factory which maps type identifiers
 * to object creators. This means that you (as the user of the factory)
 * provide a creator function for each class the factory is to instantiate.
 */


#include <iostream>
#include <loki/Factory.h>


using namespace std;
using namespace Loki;

// classes for the 'jedi factory'
struct jedi
{
      virtual ~jedi() {};
      virtual void hello() = 0;
};

struct yoda : public jedi
{
      virtual ~yoda() {};
      virtual void hello() {cout << "i'm yoda" << endl;}
};

struct mace : public jedi
{
      virtual ~mace() {};
      virtual void hello() {cout << "i'm mace" << endl;}
};

// jedi creator functions
yoda* create_yoda() {return new yoda;}
mace* create_mace() {return new mace;}

// second factory to demonstrate creating an object without
// default constructor (you could use Loki's Functor as well)
struct yavin {yavin(string sz) {cout << sz << endl;}};
yavin* create_yavin(string sz) {return new yavin(sz);}

// *** program output:
//
// i'm mace
// i'm yoda
// i'm on yavin
//
int main()
{
   // create jedi factory
   Factory<jedi, int> jedi_factory;

   // register jedi creators
   jedi_factory.Register(1, create_yoda);
   jedi_factory.Register(2, create_mace);

   // use factory to create mace
   jedi* j = jedi_factory.CreateObject(2);
   j->hello();
   delete j; j = 0;

   // use factory to create yoda
   j = jedi_factory.CreateObject(1);
   j->hello();
   delete j; j = 0;

   // second factory
   Factory<yavin, int, LOKI_TYPELIST_1(string)> fac;
   fac.Register(1, create_yavin);
   yavin* f = fac.CreateObject(1, "i'm on yavin");
   delete f; f=0;

   return 0;
}