Using constexpr array as non-type template argument (C ++ 14)

#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;
}

      

This program compiles and prints 5

with gcc 5.1 and up, but MSVC 19.10.25019 gives the following errors:

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

Is this program valid according to the C ++ 14 standard, or is gcc too lenient here?

+3


source to share


1 answer


The program is well formed as far as I can see.

As per [temp.param] / 8, the template parameter is of type const int*

, not const int[]

.

A non-standard template parameter of the "array from T

" or "function return T

" type is configured as a "pointer to T

" or "pointer to return function T

" type, respectively.

According to [temp.arg.nontype] / 1, we can use the name of a complete array object with static storage time and external link as an argument for such a template parameter:



The template argument for a non-python template-free template must be one of the following:

...

- constant expression (5.19), which denotes 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 templates, but excluding non-static class members expressed (ignoring parentheses) as &

id-expression, where id-expression is the name of an object or function, except it &

can be omitted if the name refers to a function or array, and must be omitted if the corresponding template-parameter is a reference ...

arr

is a constant expression, even though MSVC thinks it is not. This is a basic constant expression according to [expr.const] / 2 because it contains no illegal evaluations, and it is a constant expression because it points to an object with static storage duration ([expr.const] / 4).

Since the template parameter refers to an array with static storage duration, the boundaries of the array are known at the time of template creation. Therefore, it can verify that access to arr[0]

is a legitimate kernel constant expression since it has well-defined behavior and falls into the lvalue-to-rval conversion category in [expr.const] / 2:

... a non-volatile glvalue of an integral or enumerated type that refers to a non-volatile const object with a previous initialization initialized with a constant expression

+2


source







All Articles