4

正如医生所说(强调我的):

在命名空间范围内声明的以下任何名称都具有内部链接

  • 非易失性非模板非内联const 限定变量(包括 constexpr),未声明为 extern 且先前未声明为具有外部链接;

所以我希望 const 模板变量具有外部链接。所以我做了一个测试

// main.cpp
void other();

template<class T> T var = 1;
template<class T> const T constVar = 1;

int main() {
  std::cout << var<int> << ' ' << constVar<int> << std::endl;
  other();
}

// other.cpp
template<class T> T var = 2;
template<class T> const T constVar = 2;

void other() {
  std::cout << var<int> << ' ' << constVar<int> << std::endl;
}

输出是:

1 1
1 2

第二列是 for constVar,并且对于不同的行(从不同的翻译单元打印)有所不同。这让我认为它实际上具有内部链接,尽管它是一个模板。

我知道我确实违反了 ODR,但只是为了了解正在发生的事情。

那么constVar实际上有内部联系吗?如果是,文档中突出显示的片段是什么意思?如果不是,那么发生了什么,为什么我们需要这个突出显示的片段?

4

1 回答 1

0

C++14 N4296 §14.4

模板名称具有链接 (3.5)。[...] 模板定义应遵守单一定义规则(3.2)。

C++14 N4296 §3.2.6

给定这样一个名为 D 的实体在多个翻译单元中定义,则

  • D 的每个定义都应由相同的记号序列组成;[...]

如果 D 是一个模板并且在多个翻译单元中定义,那么前面的要求既适用于模板定义 (14.6.3) 中使用的模板封闭范围的名称,也适用于实例化点的依赖名称(14.6.2)。如果 D 的定义满足所有这些要求,那么行为就好像有一个 D 的定义。如果 D 的定义不满足这些要求,那么行为是未定义的

模板是隐式内联的,即具有外部链接。发生了什么 = 未定义的行为。编译器不需要诊断您的代码,并且可能会产生意外/不一致的结果。

于 2019-10-29T16:04:28.997 回答