为什么 const 会影响 gcc 中全局变量模板实例化的链接?

Why does const affect linkage of an instantiation of a global variable template in gcc?

我正在从两个翻译单元中获取以下实例化变量模板的地址:

template<class T> bool b = true;
template<class T> const bool cb = true;
template<class T> inline const bool icb = true;

我正在打印 b<int>cb<int>icb<int> 的地址。这是 clang says:

0x6030c0 0x401ae4 0x401ae5  // first translation unit
0x6030c0 0x401ae4 0x401ae5  // second translation unit

所有地址都一样,有点意料之中。这是 gcc says:

0x6015b0 0x400ef5 0x400ef4  // first translation unit
0x6015b0 0x400ef6 0x400ef4  // second translation unit

cb<int> 的地址发生变化。嗯?这是一个错误吗?如果不是,有人可以向我解释一下这种效果吗?

来自 C++ 标准(6.5 程序和链接)

3 A name having namespace scope (6.3.6) has internal linkage if it is the name of

(3.2) — a non-inline variable of non-volatile const-qualified type that is neither explicitly declared extern nor previously declared to have external linkage; or

所以变量模板的特化cb有内部链接。这意味着它的地址在不同的编译单元中可以不同。

在我看来,这似乎与 CWG Issue 1713 有关:

Linkage of variable template specializations

Given a namespace-scope declaration like

template<typename T> T var = T();

should T<const int> have internal linkage by virtue of its const-qualified type? Or should it inherit the linkage of the template?

Notes from the February, 2014 meeting:

CWG noted that linkage is by name, and a specialization of a variable template does not have a name separate from that of the variable template, thus the specialization will have the linkage of the template.

Clang 似乎在跟踪它。模板名称具有外部链接,从中衍生出来的变量也是如此。

最终,标准本身目前并没有很好地指定变量模板专业化的预期链接。它是为常规变量指定的,但模板是不同的野兽。