的函数模板明确分工导致链接错误
Functions.h:的函数模板明确分工导致链接错误
#pragma once
#include <iostream>
template<class T> void TemplatedFunction(T* p) {}
template<> void TemplatedFunction<float>(float* p) {}
template<> void TemplatedFunction<char>(char* p) {}
Functions.cpp:
#include "Functions.h"
void Test()
{
TemplatedFunction<float>(NULL);
TemplatedFunction<char>(NULL);
}
main.cpp中:
#include "Functions.h"
void Test();
int main()
{
Test();
return 0;
}
生成错误:
main.obj : error LNK2005: "void __cdecl TemplatedFunction<float>(float *)" ([email protected]@@[email protected]) already defined in Functions.obj
main.obj : error LNK2005: "void __cdecl TemplatedFunction<char>(char *)" ([email protected]@@[email protected]) already defined in Functions.obj
我知道两种方法来解决这个问题:
不包括Functions.h几个.cpp文件 - 不能在复杂的工程应用,如果H-文件包含许多需要一些额外的定义。 cpp文件。
声明所有模板函数为
static
。但是这意味着特定的函数会出现在包含Functions.h的所有.cpp文件中,即使它们未被使用,这可能会导致代码重复。
所以,我看到专门的模板功能就像非模板化功能一样。如果没有static
声明,是否有其他解决方案来防止链接器错误?如果函数声明为static
,现代C++编译器是否将它们从优化构建中删除,如果它们未被使用?
编辑。 阅读前两个答案后:我不问在这里如何防止此类链接器错误。假设我不能将专业化移动到.cpp文件并将其保留在012h或inline
的.h文件中,这是否会导致代码复制和优化版本中的膨胀,当这些函数被添加到包含.h文件的每个.cpp文件时,即使他们没有使用?
所以,我看到专门的模板函数的行为像非模板化函数。
正确。
是否有任何其他解决方案,以防止链接器错误没有
static
声明?
是,像任何正常的非模板函数:
要么定义功能特化作为inline
或申报(但不限定)标头中的专业:
template<> void TemplatedFunction<float>(float* p);
template<> void TemplatedFunction<char>(char* p);
并在Functions.cpp
中定义它们
template<> void TemplatedFunction<float>(float* p) {}
template<> void TemplatedFunction<char>(char* p) {}
它们比使用static
更好的选择,因为制作的功能的静态还有其他副作用,如给予的功能不同的地址,在每个翻译单元,并使得在每一个翻译单元不同的局部静态变量。这是一种语义变化,而不仅仅是链接器错误的解决方案。
如果函数声明为
static
,现代C++编译器是否将它们从优化构建中删除,如果它们未被使用?
是的。但是,在使用它们的任何文件中,您将得到重复的代码,使得可执行文件比仅有函数的单个定义更大。
假设我不能动专业化.cpp文件,并把它与
static
.h文件中...
我看不到任何好的理由为什么这样做是必要的,但无论如何, ...
...或
inline
,确实在优化的建立这项事业代码重复和腹胀,当这些功能被加入到其中包含的.h文件中的每个.cpp文件,即使不使用他们?
不,如果它们不在给定文件中使用,它们不会影响从该文件编译的对象的大小。
你的问题很容易让人误解,因为它似乎是关于模板的(关于模板的标题非常清楚!),但是未使用的内联/静态函数是否导致代码膨胀与函数是否是模板无关。
如果你的问题只是“做未使用的内联函数和静态函数会影响对象大小吗?”对于普通功能和功能模板,答案都是否定的。
谢谢,但我的问题的主要观点是:如果函数保留在.h文件中,是否会导致代码在优化构建中膨胀?看到我编辑的问题。 – 2014-08-27 14:55:08
答复已更新。 – 2014-08-27 15:03:14
这种明确的专业化应该移动到.cpp文件或制作inline
。链接器会在那里找到它们。如果你在头文件中定义它们,你会得到“已经定义”的错误信息,就像你在多个编译单元包含的头文件中定义的普通非内联和非静态函数一样。
谢谢,但我的问题的主要观点是:如果函数保留在.h文件中,是否会导致代码在优化构建中膨胀?看到我编辑的问题。 – 2014-08-27 14:54:45
如果您将它们设为'inline',请将这些专业化看作普通的内联函数。通常它们不应该导致任何代码膨胀,但是 - 与常规内联一样 - 有时可能值得检查并且例如将它们临时插入到.cpp中并比较可执行文件的大小。 – 2014-08-27 14:57:11
谢谢,比较可执行文件的大小是个好主意,我会这样做。 – 2014-08-27 14:59:18
显式特化的主体需要像普通的非模板函数一样进入cpp文件(这就是它们)。如果你愿意(或者有意义),你可以用'inline'交替标记它们。 – dlf 2014-08-27 14:30:58