2013-03-03 43 views
0

我在头文件中定义了以下模板函数。如何直接从通过模板函数的类型检查类型而不是从变量?

template <class T> T* spawnEnemy(SpawnDirection dir); 

我的目的是创建一个接受敌人类型作为模板参数的一般产卵功能,从函数返回衍生的对象。

以下是不正确实现,但我用它来表达我想实现的目标。

template <class T> T* ObjectSpawner::spawnEnemy(SpawnDirection dir) 
{ 
    if(_enemiesPool->isAnyFreeObjects()) 
    { 
     T* enemy = NULL; 
     if(typeof(T*) == Zombie01) // This line is INCORRECT 
      enemy = dynamic_cast<T*>(_enemiesPool->popFreeObjectAndAddToActiveListForType(ZOMBIE)); 
     else if ... 

     return enemy; 
    } 
    else 
     return NULL; 
} 

这就是我需要能够做到从类型Ť检查,这样我就可以适当地调用函数

popFreeObjectAndAddToActiveListForType(int type) 

与正确的值作为其输入。

那么如何在模板函数中这样的情况下进行类型检查呢?

编辑: 从stephen linnvoigt得到了一个建议后,我看到这个设计有一个缺陷,但这是因为我已经从我已经完成了它。更容易的是让函数具有另一个类型参数并且不涉及模板,但需要稍后转换为特定类型。无论如何,了解这种情况的解决方案是很好的。

+2

'T *'已经是一个特定的类型,一旦你实例化模板,所以我不清楚为什么你需要检查它。如果你想'T *'映射到'int type'参数的特定常量,那么你需要某种类型的特征。 – 2013-03-03 21:54:09

+1

不能用类型参数调用你的函数吗?像“模板无效popFreeObjectAndAddToActiveListForType()”?为什么要有类型的int? – nvoigt 2013-03-03 21:57:19

+1

@haxpor什么nvoight说 – 2013-03-03 22:00:13

回答

1

认为你想这样的事情(使用类型特征):

以下部分代码必须放在类部分之外。

template <typename T> 
struct EnemyTraits { }; 

template <> 
struct EnemyTraits<Zombie01> { static const int pop_type = ZOMBIE; }; 

template <> 
struct EnemyTraits<Vampire01> { static const int pop_type = VAMPIRE; }; 

应按照this中的建议在头文件中定义以下函数。

template <typename T> T* ObjectSpawner::spawnEnemy(SpawnDirection dir) 
{ 
    if(_enemiesPool->isAnyFreeObjects()) 
    { 
     const int pop_type = EnemyTraits<T>::pop_type; 
     return dynamic_cast<T*>(_enemiesPool->popFreeObjectAndAddToActiveListForType(pop_type)); 
    } 
    else 
     return NULL; 
} 
+0

谢谢,我得到了一些关于C++和这个有趣的类型特征的有用花絮。 但是,我得到了一个链接器错误,指出“架构armv7的未定义符号: ”Zombie01 * ObjectSpawner :: spawnEnemy (ObjectSpawner :: SpawnDirection)“,引用自:...”。我相信这是关于在哪里声明或自己的语法。 我看了一下[boost](http://www.boost.org/doc/libs/1_37_0/boost/type_traits/detail/is_mem_fun_pointer_impl.hpp),尽管我们不在这里做什么,但是我找不到任何错误的步骤。 – haxpor 2013-03-04 04:53:37

+0

我在头文件中定义了泛型模板,在实现文件中定义了专门化模板,因为如果我把它放在头文件中,我得到了一个编译错误。我也看看这个[link](http://accu.org/index.php/journals/442#boost),但目前为止还没有工作。 – haxpor 2013-03-04 04:56:30

+0

你把所有上面的头文件? [(有用的信息)](http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file)...你也可以做明确的实例化替代方案,但这是少一些标准 – 2013-03-04 04:56:42

1

一种可能性是使用dynamic_cast,如果T是基类的Zombie01

T *enemy = dynamic_cast<Zombie01*>(x); 
if (!enemy) 
{ 
    // x can not cast to Zombie01 
    // do something else 
} 

但是,建议尽量减少dynamic_cast

使用另一个想法是使用std::is_same

如果T和U的名称与具有相同常数的同类型 等级提供的成员常量值等于true。 否则值为false。

不过,我试图用斯科特迈尔斯的提示,从有效的C++:

“无论何时你发现自己编写形式的代码”如果对象是类型T1的 ,然后做一些事情,但如果它的类型T2的,然后做 别的事情,”掴自己

+1

我自己打了一个。 – haxpor 2013-03-03 22:17:49

+0

我尽量避免使用dynamic_cast,它需要太多if-if。此外,我现在没有使用C++ 11,所以我找不到is_same,但感谢您向我介绍它。 – haxpor 2013-03-03 22:24:05

+0

@ M.M。 fyi,如果'T'实际上是'Zombie01'的基类并不重要,dynamic_cast会[cross-cast](http://stackoverflow.com/questions/5321664/checking-whether-a-crosscast - 可能工作)任何两个多态指针。 – 2013-03-03 22:34:13

相关问题