0

标题不代表我的问题,但我找不到正确的问题,请随时编辑。

语境 :

学校的炸弹人项目。

在我的Bomberman我有一个execAfter()函数原型如下:

void execAfter(std::function<void(t_params *)> func, t_params *params, int ms);

此函数的目的是在延迟后执行func,以paramsstruct 作为参数。ms

示例:投下炸弹,X 毫秒后爆炸

它完美地工作(使用 lambda,如先前的 SO 问题中所述)。

问题

现在我想对我的函数进行模板化,以便能够传递不同的函数类型和不同的params类型。

时间.hh

template<typename T, typename U, typename V>
void execAfter(T func, U params, V ms);

时间.cpp

template<typename T, typename U, typename V>
void Time::execAfter(T func, U params, V ms)
{ 
 ...
}

(模板化V参数没用,只是编译问题,后面我会想办法)

示例:*调用函数void X(Y),作为参数传递Y*

从我的角度来看,我以正确的方式完成了一切,一切都编译了,除非在链接 gcc 抛出这个之后:

[...]
 linkage ...
[...]
 src/Entities/Character.o: In function `Character::landBomb()':
 /home/teube_a/Code/tech2/c++/bomberman-2016-      couille_c/zizi_g/src/Entities/Character.cpp:208: undefined reference to `void   Time::execAfter<std::function<void (s_params*)>, s_params*, int>(std::function<void  (s_params*)>, s_params*, int)'
 collect2: ld returned 1 exit status
 make: *** [bomberman] Error 1

我真的不明白,请解释一下这个模板化函数无法生成的可能原因。

如果您需要更多信息,请告诉我。

4

1 回答 1

3

在 C++ 中,模板被理解为编译器生成代码的模板。所以编译器必须在模板的每个实例化时知道实现是什么,即它应该在定义模板的头文件中。

你可以有这样的模板的具体实现:

template <typename T>
T f(T) { ...}

template<> 
int f<int>(int) {...} 

然后链接器将找到具体类型的实现,并将优先使用它而不是编译器生成的版本。

您现在拥有的是没有实现的模板声明,这意味着链接器将仅搜索具体的实现,而找不到!

有两种可能的解决方案:

  1. 您提供默认模板实现,而不仅仅是签名
  2. 您为请求的类型提供模板的具体化。请记住,您必须/能够为您的模板应该使用的每种类型执行此操作。
于 2013-05-28T14:20:46.753 回答