I have class World which manages creation of object… After creation it calls afterCreation method and I the created object is user-defined type derived from Entity (eg. MyEntity), I want to call addEntity. I the object was something else, I want to do nothing.
addEntity must be called with appropriate T, because it generates unique IDs for every derived class etc.
Here is my solution:
template <int v>
struct ToType
{
enum { value = v };
};
template <typename T>
void World::afterCreation(T * t)
{
afterCreation(t, ToType<std::is_base_of<Entity, T>::value>());
}
template <typename T>
void World::afterCreation(T * t, ToType<true>)
{
addEntity(t); //here I cant pass Entity *, I need the real type, eg. MyEntity
}
template <typename T>
void World::afterCreation(T * t, ToType<false>)
{
}
My question is – Can in be done better way?
How can I simulate following code without ToType or similar?
template <typename T>
void afterCreation(){/*generic impl*/}
template <typename T where T is derived from Entity>
void afterCreation(){/*some specific stuff*/}
- “specialize” in the title is only to describe my intention, no need to solve problem with template specialization
It is not going to make it much better, but you can remove one level of indirection by using SFINAE:
How does this work? When the compiler finds the call to
afterCreationit tries to determine which of the overloads is best, and for that it matches the types and tries to perform the substitution. In both cases, the matched type (from the arguments) and apply the substitution to the whole expression. Theenable_iftemplate contains an inner typetypeif the value passed as the first argument istrueor else it does not contain such type. During the substitution of the types, one of the overloads will yield an invalid function signature (the one for which the condition is false) and will be dropped from the set of candidates.