以下程序是否应按标准编译?

时间:2015-09-06 10:37:37

标签: c++ visual-c++ template-specialization class-template

在我发现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的非专业定义移出结构定义,甚至将其置于特化声明之上使得程序成功,但我想确定。

所以我的问题是 - 是否应该通过符合标准的编译器/链接器编译和链接此程序而不会出错?

2 个答案:

答案 0 :(得分:1)

来自标准:

  

©ISO / IEC N4527   14.6.4.1实例化点[temp.point] 1对于函数模板特化,成员函数模板特化,或者   成员函数或类的静态数据成员的特化   模板,如果由于它而隐式实例化特化   从另一个模板专业化和   引用它的上下文取决于模板参数,   专业化实例化的重点是   封闭专业化的实例化。 否则,重点   这种专业化的实例化紧随其后   命名空间范围声明或引用的定义   专业化

在这种情况下,我认为这意味着在C.h发生了“范围声明”。如果是这种情况,那么您的代码应该与标准兼容的工具链链接。我可能误解了这个......

答案 1 :(得分:-2)

未命名的命名空间具有内部链接。由于模板特化是在未命名的命名空间内,因此它也具有内部链接。

要解决此问题,请将模板放在命名的命名空间中,或将专门化指定为&#39; extern&#39;。