我有World管理对象创建的类...在创建之后调用afterCreation方法,我创建的对象是从Entity(例如MyEntity)派生的用户定义类型,我想调用addEntity.我的对象是别的,我什么都不做.
addEntity必须使用适当的调用T,因为它为每个派生类等生成唯一的ID.
这是我的解决方案:
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>)
{
}
Run Code Online (Sandbox Code Playgroud)
我的问题是 - 可以做得更好吗?
如何在没有ToType或类似的情况下模拟以下代码?
template <typename T>
void afterCreation(){/*generic impl*/}
template <typename T where T is derived from Entity>
void afterCreation(){/*some specific stuff*/}
Run Code Online (Sandbox Code Playgroud)
它不会让它变得更好,但您可以使用 SFINAE 删除一级间接:
template <typename T>
typename std::enable_if< std::is_base_of<Entity, T>::value >::type
World::afterCreation(T * t)
{
// Derived from Entity
}
template <typename T>
typename std::enable_if< !std::is_base_of<Entity, T>::value >::type
World::afterCreation(T * t)
{
// generic
}
Run Code Online (Sandbox Code Playgroud)
这是如何运作的?当编译器找到对其的调用时,它afterCreation会尝试确定哪个重载是最好的,并为此匹配类型并尝试执行替换。在这两种情况下,匹配类型(来自参数)并将替换应用于整个表达式。如果作为第一个参数传递的值是,则模板enable_if包含内部类型,否则模板不包含此类类型。在类型替换期间,其中一个重载将产生无效的函数签名(条件为 false 的函数签名),并将从候选集中删除。typetrue