以下代码位于.h文件中(包含保护)
template<typename T1, typename T2> // a
void func(T1 const &t1, T2 const &t2)
{
std::cout << "\nbase template";
}
template<> // b
inline void func<int, int>(int const &t1, int const &t2)
{
std::cout << "\nspecialization for integers";
}
从(b)中删除inline关键字时,以下代码(从包含.h的.cpp调用)将无法编译
func<int, int>(1, 2);
发出链接器错误“错误LNK2005:”void __cdecl func(int const&amp;,int const&amp;)“(?? $ func @HH @@ YAXABH0 @ Z)已在ConsoleApplication1.obj中定义”
为什么会这样?
编辑:
因为它们是定义(由Luchian Grigore回答),显式特化是否意味着显式实例化或者这个编译器是否具体?
答案 0 :(得分:5)
因为显式特化是定义,因此在多个翻译单元中包含该文件会导致多次定义符号,这会破坏一个定义规则。
除了标记inline
之外,您可以将声明留在标题中并将定义移动到实现文件中。
答案 1 :(得分:2)
您只能使用类型本身直接覆盖它,而无需编写模板:
void func(int const &t1, int const &t2)
{
std::cout << "\nspecialization for integers";
}
现在,错误发生是因为如果包含头部,那么如果在头部中定义的函数最终会出现在两个cpp文件中,那么将会有两个相同函数的声明(如错误所示:already defined
)导致链接错误。要解决这个问题,只需在没有实现的情况下在头文件中编写声明,并在其中一个头文件中移动实现:
//header
void func(int const &t1, int const &t2);
//cpp file
void func(int const &t1, int const &t2)
{
...
}