(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.
If you don't want to use
virtual, you can use templates. The name of this idiom is Curiously recurring template pattern, and it's used in ATL and WTL.Look code.
(live example)
If you want to make
BinheritA, code like this:(live example)
My example code uses compile-time polymorphism. So, it cannot be applied in runtime. If you want to get "FunnyName" in runtime, you should use
virtual, run-time polymorphism.Curiously recurring template pattern works like this:
You may see the basic form of the pattern.
The derived class inherit
Super, withDeriveditself as template parameter.Super<Derived>is concretized like this:On
1, we're castingthispointer intoDerived *, and callfoowith this casted pointer on2. Since the type of pointer isDerived *,thiz->foo();statement will callDerived::foo.(wikipedia page explanation seems good)