函数模板的显式特化会导致链接器错误

Ale*_*x F 9 c++ templates template-specialization

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) {}
Run Code Online (Sandbox Code Playgroud)

Functions.cpp:

#include "Functions.h"

void Test()
{
    TemplatedFunction<float>(NULL);
    TemplatedFunction<char>(NULL);
}
Run Code Online (Sandbox Code Playgroud)

main.cpp中:

#include "Functions.h"
void Test();

int main()
{
    Test();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

构建错误:

main.obj : error LNK2005: "void __cdecl TemplatedFunction<float>(float *)" (??$TemplatedFunction@M@@YAXPAM@Z) already defined in Functions.obj
main.obj : error LNK2005: "void __cdecl TemplatedFunction<char>(char *)" (??$TemplatedFunction@D@@YAXPAD@Z) already defined in Functions.obj
Run Code Online (Sandbox Code Playgroud)

我知道有两种解决方法:

  1. 不要将Functions.h包含在几个.cpp文件中 - 如果h文件包含许多.cpp文件中需要的一些其他定义,则不能在复杂项目中应用.

  2. 将所有模板化函数声明为static.但这意味着专用函数出现在包含Functions.h的所有.cpp文件中,即使它们未被使用,也可能导致代码重复.

所以,我看到专门的模板化函数表现得像非模板化函数.是否还有其他解决方案可以在没有static声明的情 如果声明了函数static,那么现代C++编译器是否会从优化构建中删除它们(如果它们未被使用)?

编辑. 在阅读前两个答案后:我不在这里问如何防止这样的链接器错误.假设我无法将专门化移动到.cpp文件并将其保留在带有static或的.h文件中inline,这会导致代码重复和优化构建中的膨胀,当这些函数被添加到包含.h文件的每个.cpp文件中时,即使他们没用过?

Jon*_*ely 17

所以,我看到专门的模板化函数表现得像非模板化函数.

正确.

是否还有其他解决方案可以在没有static声明的情

是的,就像任何普通的非模板功能一样:

无论是定义功能特化inline

声明(但不定义)标题中的特化:

template<> void TemplatedFunction<float>(float* p);

template<> void TemplatedFunction<char>(char* p);
Run Code Online (Sandbox Code Playgroud)

并在中定义它们 Functions.cpp

template<> void TemplatedFunction<float>(float* p) {}

template<> void TemplatedFunction<char>(char* p) {}
Run Code Online (Sandbox Code Playgroud)

这些是比使用更好的选项static,因为使函数静态具有其他副作用,例如在每个翻译单元中赋予函数不同的地址,以及使每个翻译单元中的局部静态变量不同.这是一个语义变化,而不仅仅是链接器错误的解决方案.

如果声明了函数static,那么现代C++编译器是否会从优化构建中删除它们(如果它们未被使用)?

是.但是在使用它们的任何文件中,您将获得重复的代码,使得可执行文件比函数的单个定义更大.

假设我无法将专业化移动到.cpp文件并将其保留在.h文件中static...

我看不出有什么理由需要,但无论如何......

...或者inline,当这些函数被添加到包含.h文件的每个.cpp文件中时,这是否会导致代码重复和膨胀,即使它们未被使用?

不,如果它们未在给定文件中使用,则它们不会影响从该文件编译的对象的大小.

您的问题具有误导性,因为它似乎与模板有关(标题非常清楚模板!)但是,未使用的内联/静态函数是否会导致代码膨胀与函数是否为模板无关.

如果您的问题只是"未使用的内联函数和静态函数会影响对象大小吗?" 对于正常功能和功能模板,答案是否定的.