如何为从特定类型派生的类型专门化模板



我有一个类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>)
{
}

我的问题是——能做得更好吗?

在没有ToType或类似代码的情况下,我如何模拟以下代码?

template <typename T>
void afterCreation(){/*generic impl*/}
template <typename T where T is derived from Entity>
void afterCreation(){/*some specific stuff*/}
  • 标题中的"specialize"只是描述我的意图,不需要解决模板专业化的问题

这不会让它变得更好,但您可以通过使用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
}

这是怎么回事?当编译器找到对afterCreation的调用时,它会尝试确定哪个重载是最佳,并为此匹配类型并尝试执行替换。在这两种情况下,匹配类型(来自参数)并将替换应用于整个表达式。如果作为第一个参数传递的值是true,则enable_if模板包含内部类型type,否则它不包含此类类型。在替换类型的过程中,其中一个重载将产生无效的函数签名(条件为false的函数签名),并将从候选函数集中删除。

您可以使用多态指针:

template <typename T>
void afterCreation(T* x) {
    T* entity = dynamic_cast<Entity*> x;
    if (!entity) {
        // ... generic implementation
    } else {
        // ... entity implementation, use "entity"
    }
}

尽管这可能不是最好的解决方案,因为它有(微小的)运行时开销。一个非常聪明的编译器可能会通过静态分析来消除这种开销,但我怀疑编译器是否会接受这一点。

最新更新