Reflection is C++ ?
Hi, how can I perform "reflection" in C++ ? Is it possible? My situation is as follow: application will consume a string that contains whitespace-separated fields. One of the field describes the class name. Based on this string, I'll create the appropriate objects. So basically it'll looked like this: T& createObj() { vector<string> argv; //read line and populate argv //Set T = class to be instantiated. return T::createObj(argv); } -- -- Verdi March --
Hi, On Wednesday 11 June 2003 18:28, Verdi March wrote:
Hi,
how can I perform "reflection" in C++ ? Is it possible?
My situation is as follow: application will consume a string that contains whitespace-separated fields. One of the field describes the class name. Based on this string, I'll create the appropriate objects. So basically it'll looked like this:
T& createObj() { vector<string> argv; //read line and populate argv
//Set T = class to be instantiated.
return T::createObj(argv); }
Forgot the question: how to do "set T = class to be instantiated" ? -- -- Verdi March --
On Wednesday 11 June 2003 12:28, Verdi March wrote:
how can I perform "reflection" in C++ ? Is it possible?
T& createObj() { vector<string> argv; //read line and populate argv
//Set T = class to be instantiated.
return T::createObj(argv); }
You'll need a large if...else construct to do that and preferably a common superclass for the classes you want to return: T & createObj() { vector<string> argv; ... // read T vehicle = 0; if ( input == "plane" ) vehicle = new plane(); else if ( input == "train" ) vehicle = new train(); else if ( input == "car" ) vehicle = new car(); else { // handle input error } return vehicle; } -- Stefan Hundhammer <sh@suse.de> Penguin by conviction. YaST2 Development SuSE Linux AG Nuernberg, Germany
This can get real messy as you start adding more types, I would suggest using the factory method for doing this. Basically, use inheritance with a static function inside of each derived type that returns an instance of itself. Then create a map which associates a string "train", "car", etc... with the appropriate create function. This does the same thing as the code below but does it in a single line. class Base { .... } class Train : public Base { ... static Train * create() { return new Train } ... } class Car : public Base { ... static Car * create() { return new Car } ... } int main() { map funcs<string, void (*create)()>; //these functions must be register into the map, but only once funcs["train"] = Train::create; funcs["car"] = Car::create vehicle = funcs["car"](); //returns a pointer to a car }
You'll need a large if...else construct to do that and preferably a common superclass for the classes you want to return:
T & createObj() { vector<string> argv; ... // read T vehicle = 0;
if ( input == "plane" ) vehicle = new plane(); else if ( input == "train" ) vehicle = new train(); else if ( input == "car" ) vehicle = new car(); else { // handle input error }
return vehicle; }
-- Tom Bradley Software Engineer Jaycor / Titan Systems
I go even further by making the map a static field of the base class and using a function call in the class header of each subclass: #ifndef TRAIN #define TRAIN class Train : public Base { ... }; namespace { void *dummyTrain = Base::addEntry( "Train", Train::create() ); } #endif where Base::addEntry() looks something like private: typedef Base *(*Create)( string& name ); public: void *addEntry( string Name, Create create ){ funcs[ name ] = create; return 0; } This allows the subclasses to add their own entries to the map, which is contained in the base class. This makes it easier to create new classes in future. The void *dummyTrain stuff is a bit clunky. I don't know if there's a more elegant way to defer construction of the map until runtime. Tom Bradley wrote:
class Base { .... }
class Train : public Base { ... static Train * create() { return new Train; } ... };
class Car : public Base { ... static Car * create() { return new Car; } ... };
int main() { map funcs<string, void (*create)()>; //these functions must be register into the map, but only once funcs["train"] = Train::create; funcs["car"] = Car::create
vehicle = funcs["car"](); //returns a pointer to a car }
-- JDL Non enim propter gloriam, diuicias aut honores pugnamus set propter libertatem solummodo quam Nemo bonus nisi simul cum vita amittit.
Verdi March <cincaipatron@gmx.net> [Wed, 11 Jun 2003 18:28:07 +0800]:
how can I perform "reflection" in C++ ? Is it possible?
It won't help in this case, but for advanced template stuff check the boost library at www.boost.org and for reflection http://www.boost.org/libs/type_traits/index.htm Philipp
participants (5)
-
John Lamb
-
Philipp Thomas
-
Stefan Hundhammer
-
Tom Bradley
-
Verdi March