在我发现MSVC和GCC(可能也是clang)在编译和链接相同代码时不一致之后,我开始好奇这个程序是否应该实际编译和链接,因此它是MSVC中的错误(报告链接器错误),或者我应该用不同的方式编写它。该程序由3个文件组成:
刘昀
template <typename T>
struct A
{
void func() {};
};
template <>
void A<int>::func ();
A.cpp:
#include "C.h"
int main()
{
A<int> x;
x.func();
}
B.cpp:
#include "C.h"
template <>
void A<int>::func()
{
}
从MSVC得到的链接错误是:
。外部符号"public: void __thiscall A::func(void)"无法解析
所以基本上它决定不创建超出B.cpp
定义的符号。让我强烈怀疑这是一个bug的事情是,将func
的非专门化定义移出结构定义,甚至将其置于专门化声明之上,使程序链接成功,但我想确定。
所以我的问题是-这个程序应该由一致的编译器/链接器编译和链接没有错误吗?
从标准:
©ISO/IEC N452714.6.4.1实例化点[temp.point] 1对于函数模板特化,成员函数模板特化,或成员函数或类的静态数据成员的专门化模板,如果特化被隐式实例化,因为它从另一个模板专门化中引用的引用它的上下文取决于模板参数,专门化的实例化点是封闭专门化的实例化。否则,点的实例化后紧跟着的名称空间作用域声明或定义专业化 .
在这种情况下,我认为意味着在C.h发生"作用域声明"的地方。如果是这种情况,那么您的代码应该与标准兼容的工具链链接。我可能误解了…
未命名的名称空间具有内部链接。因为模板专门化是在一个未命名的命名空间中,所以它也有内部链接。
要解决这个问题,将模板放在一个命名的命名空间中,或者将专门化指定为'extern'。