see std::map. The clean way to implement the above in c++ is to have a
std::map<int, Object*> and use a clone() method to get your prototype.
The translation unit that defines the subclass in question takes care of
inserting the instance into the map.
e.g.
template <class T> insert_into_map {
insert_into_map(std::string s) {
T* x = new T;
the_map().insert(s,x); // the_map is the global table
}
};
class Circle {
....
};
namespace {
insert_into_map <Circle> x("Circle);
};
Object* make_object(const std::string & id){
std::map<std::string,Object*>::iterator it = the_map().find(id);
if (it==the_map().end())
return NULL;
else return it->second->clone();
}
This also has the advantage that you can populate the map at runtime if
you
dynamically load the code that defines circle (so you get runtime plugin
support)
IMHO, anything solution to a problem so simple as choosing a path from 3-5
static options that uses templates and complex logic is really overthinking
the problem. The resultant code is going to be slower, the time to fix bugs
is going to increase, and the code understandability goes down.
Also, in the case you want dynamic lookups, I would recommend a factory
approach over a cloning approach. That not only allows you dynamic lookups,
but also allows dynamic parameters and saves you from having to design a
class so it can be instantiated without actually doing its work.
The equivilent C# code(using generics partially) would be...
public interface IObjectFactory
{
object CreateObject(object[] arguments);
}
public class MapLookupClass
{
Dictionary<short,IObjectFactory> dict = new Dictionary<short,object>();
public vpod InsertIntoMap(short id, IObjectFactory factory)
{
dict.Add(id,objectFactory);
}
public MakeObject(short id, object[] arguments)
{
IObjectFactory fac;
fac = dict[id];
return fac.CreateObject(arguments);
}
}
It is more readable than the C++ approach, IMHO, but it is still
considerably less readable than a simple switch.
It doesn't strive to achieve automatic registration as yours does, although
I think that is possible I don't have a compiler on hand to write something
to test it and get the syntax right ATM. I would probably use attributes and
reflection anyway.