在我发现MSVC和GCC之间的不兼容性(也可能是clang)编译和链接相同的代码之后,如果这个程序实际编译和链接我就会感到好奇,因此它是MSVC中的错误(报告链接器错误) )或者我应该以不同的方式写它。该计划包括3个文件:
C.h
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产生的链接器错误是:
A.obj:错误LNK2019:未解析的外部符号“public:void __thiscall A :: func(void)”
所以基本上它决定不在B.cpp
中的定义中创建符号。让我强烈怀疑它是一个错误的事情是,将func
的非专业定义移出结构定义,甚至将其置于特化声明之上使得程序成功,但我想确定。
所以我的问题是 - 是否应该通过符合标准的编译器/链接器编译和链接此程序而不会出错?
答案 0 :(得分:1)
来自标准:
©ISO / IEC N4527 14.6.4.1实例化点[temp.point] 1对于函数模板特化,成员函数模板特化,或者 成员函数或类的静态数据成员的特化 模板,如果由于它而隐式实例化特化 从另一个模板专业化和 引用它的上下文取决于模板参数, 专业化实例化的重点是 封闭专业化的实例化。 否则,重点 这种专业化的实例化紧随其后 命名空间范围声明或引用的定义 专业化强>
在这种情况下,我认为这意味着在C.h发生了“范围声明”。如果是这种情况,那么您的代码应该与标准兼容的工具链链接。我可能误解了这个......
答案 1 :(得分:-2)
未命名的命名空间具有内部链接。由于模板特化是在未命名的命名空间内,因此它也具有内部链接。
要解决此问题,请将模板放在命名的命名空间中,或将专门化指定为&#39; extern&#39;。