【问题标题】:Should the following program compile according to standard?下面的程序应该按照标准编译吗?
【发布时间】:2015-12-02 01:30:51
【问题描述】:

在我发现 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 : error LNK2019: unresolved external symbol "public: void __thiscall A::func(void)"

所以基本上它决定不创建放在B.cpp 中的未定义符号。让我强烈怀疑它是一个错误的事情是,将func 的非专业定义从结构定义中移出,甚至将其置于专业化声明之上,这使得程序链接成功,但我想确定一下。

所以我的问题是 - 这个程序是否应该由符合标准的编译器/链接器编译和链接而没有错误?

【问题讨论】:

  • 对我来说看起来像一个错误。您使用的是最新 (2015) 版本的 MSVC 吗?
  • @MatsPetersson 是的,2015 年。
  • 您的代码也可以使用 clang++ 编译。这有点奇怪,因为您本质上为func 提供了两个定义 - 我还不足以作为语言律师来判断这是否正确(我认为是)
  • 顺便也用clang++ -std=c++03 编译。
  • 我的评论主要是为了说明问题出在哪里,这绝对是编译器中的一个错误,如果其他人遇到这个问题,请给出解决方法。随时向 Microsoft 报告。

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


【解决方案1】:

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

要解决此问题,请将模板放在命名空间中或将特化指定为“extern”。

【讨论】:

  • “未命名的命名空间”并不像你想象的那样。
【解决方案2】:

来自标准:

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

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

【讨论】:

    猜你喜欢
    • 2017-04-29
    • 2013-06-20
    • 1970-01-01
    • 2012-01-14
    • 2010-10-11
    • 2018-08-20
    • 2018-02-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多