(This question is related to reflection, but isn't really about reflection)
I have this hierarchy of classes (say class A
and class B : public A
), and in addition to instance-specific data, I'd like to have class-specific data shared by all instances. For example, suppose I want to have a FunnyClassName
string for each of my classes.
I would like to be able to have non-virtual getters for my per-class data, such as:
/*can it be static? */ const std::string& A::GetFunnyName();
and the most important thing is that I want to have no, or as little as possible, boilerplate code in inheriting classes. The getters are to be implemented once in class A
(the root of the class hierarchy); class B should specify its FunnyClassName some other way.
It's been suggested (e.g. indirectly in questions here on SO) that a Multiton object, using the class' type hash as a key, might be the basis of a reasonable solution. Is that the case? Is there 'standard' code which does this (e.g. in the STL or in Boost)? Is there another relevant approach?
Notes:
- Think this is impossible? See this question and this (laconic) answer. But as some commenters and responders suggest, it may be necessary to have non-static getters, and make the weaker constraint of not having to rewrite the getter for every class (i.e. using RTTI).
- If C++ had static virtual data members, this would be trivial -
virtual static const std::string FunnyName
. With static virtual methods it would also be possible but only if we drop our demand for the getter only being implemented in the base class. We would have something like/* static??*/ static const std::string& A::GetFunnyName() { return "Aye"; }
and/* static??*/ const std::string& B::GetFunnyName() { return "Bee"; }
. - I'm not particularly interested in the case of templated classes, but if you want to address that as well, that's nice.
- FunnyName() is just an example. It could be
const Thing& GetFunnyThing()
. I don't want anything like the class' name from typeid.name(), or its demangling, or such. - C++11 is ok, but a solution in C++03 would be better. No C++14 please.
I am not sure this answers the question, but you should consider using
typeid
. This is a part of RTTI, so it can distinguish static and dynamic types.Have the following code in your base class:
The strings returned for different derived classes will be different; however, you don't have any control on what these strings will look like (they may contain e.g. a mangled version of the type name).
You may want to use a
std::map
to translate these system-generated names into more preferred ones likeFunnyName1
,FunnyName2
etc, but you cannot extract the name of the derived class (or maybe you can, but not in a portable way).Here is a demo.
Edit: since you really want to work with
FunnyThing
and not withFunnyName
, you should definitely use amap
. Make it a static object:Then use it to convert
string
toThing
:Now each derived class should use
RegisterThing
to "declare" whichThing
it wants to return.Calling this method only once, and at the correct time, can be implemented in different ways (like the Singleton pattern can be), so I don't want to complicate matters by giving an example.