#include <iostream>
#include <string>
#include <map>

template<class ID,class Base,class ... Args> class GenericObjectFactory{
private:
    typedef Base* (*fInstantiator)(Args ...);
    template<class Derived> static Base* instantiator(Args ... args){
        return new Derived(args ...);
    }
    std::map<ID,fInstantiator> classes;
 
public:
    GenericObjectFactory(){}
    template<class Derived> void add(ID id){
        classes[id]=&instantiator<Derived>;
    }
    fInstantiator get(ID id){
        return classes[id];
    }

};

using namespace std;
         
class Animal{
public:
    Animal(bool isAlive,string name) : isAlive(isAlive),name(name){};
    bool isAlive;
    string name;
    virtual string voice() const=0;
};
class Dog : public Animal{
public:
    using Animal::Animal;
    string voice() const{
        return this->isAlive?
            "Woof! I'm "+this->name+"\n":
            "";
    }
};
class Cat : public Animal{
public:
    using Animal::Animal;
    string voice() const{
    	return this->isAlive?
            "Meow, I'm "+this->name+"\n":
            "";
    }
};
         
int main(void){
    GenericObjectFactory<string,Animal,bool,string> animalFactory;
    
    animalFactory.add<Dog>("man's friend");
    animalFactory.add<Cat>("^_^");
    
    Animal *dog1=animalFactory.get("man's friend")(true,"charlie");
    Animal *dog2=animalFactory.get("man's friend")(false,"fido");
    Animal *cat =animalFactory.get("^_^")(true,"begemoth");
    
    cout << dog1->voice()
         << dog2->voice()
         << cat ->voice();
    return 0;
}
