在另一个问题的讨论中,我得到了一个例子,其中标识符的链接显然影响了它在常量表达式中的可用性:
extern char const a[] = "Alpha";
char constexpr b[] = "Beta";
char const g[] = "Gamma";
template <const char *> void foo() {}
auto main()
-> int
{
foo<a>(); // Compiles
foo<b>(); // Compiles
foo<g>(); // Doesn't compile
}
最后一个错误(使用 GCC)是:
test.cc: In function 'int main()':
test.cc:12:13: error: the value of 'g' is not usable in a constant expression
foo<g>(); // Doesn't compile
^
test.cc:3:16: note: 'g' was not declared 'constexpr'
char const g[] = "Gamma";
^
我可能错过了前面讨论中示例的重要性,因为我认为它不可能只是链接来区分 foo<a>
来自 foo<g>
- 然而,我已经开始怀疑那个立场了。
- 真的是链接,还是
extern
授予的其他属性? , 这允许foo<a>()
? - 允许
foo<a>()
的理由是什么?但不是foo<g>()
?特别是,如果是由链接决定的,为什么内部链接会导致一个变量在声明相同的变量时不能用作常量表达式extern
会有用吗? - 建议符号对链接器可见(或不可见)的问题与此处相关。在我看来,
foo<b>
即使static
仍然允许变体添加的内容反驳了这一点 - 还是我弄错了? - (我认为
foo<b>()
和foo<g>()
之间的差异已被 other questions 充分覆盖)。
最佳答案
GCC 错误。
N3337(这是 C++11 + 编辑修复)[temp.arg.nontype]/2 有一个直接的例子:
template<class T, const char* p> class X {
/* ... */
};
X<int, "Studebaker"> x1; // error: string literal as template-argument
const char p[] = "Vivisectionist";
X<int,p> x2; // OK
在 C++03 中,引用/指针模板参数仅限于具有外部链接的事物,但在 C++11 中该限制已被删除。
引用/指针模板参数的规则在 C++17 中放宽以允许所有常量表达式,所以 GCC 接受带有 -std=c++1z
的示例的原因可能是它在该模式下通过不同的代码路径。
关于c++ - 为什么外部链接变量可用作常量表达式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40227583/