c++ - 使用 constexpr 数组作为模板非类型参数 (C++14)

标签 c++ gcc visual-c++ c++14 constexpr

#include <iostream>

using namespace std;

template<const int arr[]>
struct S {
    static constexpr int value = arr[0];
};

constexpr int arr[] = { 5 };

int main() {
    cout << S<arr>::value << endl;
}

此程序编译良好并使用 gcc 5.1 及更高版本打印 5,但 MSVC 19.10.25019 给出以下错误:

error C2975: 'S': invalid template argument for 'arr', expected compile-time constant expression error C2131: expression did not evaluate to a constant

这个程序是否符合 C++14 标准,或者 gcc 在这里太宽松了?

最佳答案

据我所知,该程序格式正确。

根据 [temp.param]/8,模板参数实际上具有类型 const int*,而不是 const int[]

A non-type template-parameter of type “array of T” or “function returning T” is adjusted to be of type “pointer to T” or “pointer to function returning T”, respectively.

根据[temp.arg.nontype]/1,我们可以使用具有静态存储持续时间和外部链接的完整数组对象的名称作为这样一个模板参数的实参:

A template-argument for a non-type, non-template template-parameter shall be one of:

...

— a constant expression (5.19) that designates the address of a complete object with static storage duration and external or internal linkage or a function with external or internal linkage, including function templates and function template-ids but excluding non-static class members, expressed (ignoring parentheses) as & id-expression, where the id-expression is the name of an object or function, except that the & may be omitted if the name refers to a function or array and shall be omitted if the corresponding template-parameter is a reference ...

arr 是一个常量表达式,尽管 MSVC 认为它不是。根据 [expr.const]/2,它是一个核心常量表达式,因为它不包含任何禁止的计算,并且它是一个常量表达式,因为它指向一个具有静态存储持续时间的对象 ([expr.const]/4)。

因为模板参数引用了一个静态存储持续时间的数组,所以数组的边界在模板实例化时是已知的。因此它可以验证对 arr[0] 的访问是合法的核心常量表达式,因为它具有明确定义的行为并且属于 [expr.const 中允许的左值到右值转换的类别]/2:

... a non-volatile glvalue of integral or enumeration type that refers to a non-volatile const object with a preceding initialization, initialized with a constant expression

关于c++ - 使用 constexpr 数组作为模板非类型参数 (C++14),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43528101/

相关文章:

c - Printf 参数顺序被忽略

c - 为什么函数的参数被写入主堆栈帧而不是函数堆栈帧?

c++ - 如何处理成员函数中的递归?

c++ - 使用顶点缓冲区对象在 OpenGL 中的曲面绘制中出现不希望的锯齿

gcc 4.4.7 : base class subobject padding occupied in derived class object 的 C++ 对象模型

windows - VisualC++/vmg/vms 的 G++ 等效项

c++ - 为什么在 MSVC 中默认将浮点值(如 3.14)视为 double 值?

c++ - 在 Visual C++ 中将 std::string 添加到 uint 时出现模棱两可的错误

c++ - 按值传递类时,调用者或被调用者是否调用析构函数?

c++ - C++ 中的异常,函数指针为 : Access violation executing location 0x00000000