c++ - 为什么外部链接变量可用作常量表达式?

标签 c++

在另一个问题的讨论中,我得到了一个例子,其中标识符的链接显然影响了它在常量表达式中的可用性:

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> - 然而,我已经开始怀疑那个立场了。

  1. 真的是链接,还是extern 授予的其他属性? , 这允许 foo<a>() ?
  2. 允许foo<a>() 的理由是什么?但不是 foo<g>() ?特别是,如果是由链接决定的,为什么内部链接会导致一个变量在声明相同的变量时不能用作常量表达式extern 有用吗?
  3. 建议符号对链接器可见(或不可见)的问题与此处相关。在我看来,foo<b>即使 static 仍然允许变体添加的内容反驳了这一点 - 还是我弄错了?
  4. (我认为 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/

相关文章:

c++ - 两个8位数组协方差的快速实现

c++ - 使用TBB并行创建 vector

c++ - 检查模板中 nullptr 的函数指针以获取任何类型的可调用

在 char* 数组中查找 char* 类型的 c++ 程序

c++ - 使用 std::async 从线程调用函数?

c++ - 将行和列传递给函数

c++ - 我可以告诉 nvcc 将 #pragma unroll 应用于函数中的所有循环吗?

c++ - C++ 库命名空间和 C linux 函数之间的名称冲突

c++ - 用户定义文字参数中的初始化列表

c++ - 无法在 QT C++ 中获取目录大小