函数模板的显式专用化会导致链接器错误
Explicit specialization of function templates causes linker error
函数.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.cp:
#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 *)" (??$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
我知道两种解决方法:
不要将Functions.h包含在几个.cpp文件中-如果h-file包含许多.cpp文件所需的一些附加定义,则不能应用于复杂的项目中。
将所有模板化函数声明为
static
。但这意味着,专用函数会出现在包含functions.h的所有.cpp文件中,即使不使用它们,也可能导致代码重复。
因此,我看到专门的模板化函数的行为与非模板化函数类似。是否有其他解决方案可以在没有static
声明的情况下防止链接器错误?如果函数被声明为static
,那么如果不使用它们,现代C++编译器是否会将它们从优化构建中删除?
编辑在阅读了前两个答案后:我在这里不问如何防止这样的链接器错误。假设我不能将专用化移动到.cpp文件,并将其保留在带有static
或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文件中时,即使不使用它们,这是否会导致优化构建中的代码重复和膨胀?
不,如果它们没有在给定的文件中使用,它们将不会影响从该文件编译的对象的大小。
您的问题具有误导性,因为它似乎是关于模板的(标题非常清楚地是关于模板!),但未使用的内联/静态函数是否会导致代码膨胀与函数是否为模板无关。
如果你的问题只是"未使用的内联函数和静态函数会影响对象大小吗?"对于普通函数和函数模板,答案都是否定的。
此类明确的专业化应移动到.cpp文件或使其成为inline
。链接器会在那里找到它们。如果在头中定义它们,则会得到"已定义"的错误消息,就像在由多个编译单元包含的头中定义的普通非内联和非静态函数中得到它们一样。
- 静态数据成员的问题-修复链接错误会导致编译器错误
- Visual Studio mkl_link_tool.exe链接错误
- C++ 实现模板单例类时出现链接错误
- 使用类模板的方法链接错误
- MySQL C++连接器链接错误
- VS 2015 链接错误 无法构建依赖于 libcurl 的项目
- 运行 C++ 单元测试时LNK2005链接错误
- 对 CMake 中'cudaRegisterLinkedBinary'链接错误的未定义引用?
- 链接错误,包括我创建的相同头文件 - C++
- 在Embarcadero C++ Builder中生成的DLL未解决的外部链接错误
- 使用标头保护的多个定义链接错误
- 链接错误:未定义对 stdscr 和 wgetch 的引用
- 使用 Vivek 的 Vcam / 捕获源过滤器构建/链接错误
- 升压program_options中的链接错误
- 使用 g++ 预处理器进行替换会导致链接错误
- 在调试配置中编译工作正常,但发布会给出链接错误
- 相邻矩阵设置链接错误
- 包含常量变量并包含在多个文件中的标头的链接错误
- C++链接错误,我理解但无法解决
- 是什么导致macOS Mojave上的GoogleTest链接错误