C++ Constexpr和模板:编译器错误?

C++ Constexpr和模板:编译器错误?,c++,templates,constexpr,C++,Templates,Constexpr,以下工作如预期: #include <array> constexpr std::array<int, 3> values = {1, 2, 3}; template <int i> struct A { static constexpr int val = values[i]; }; int main() { A<1> a; } 错误是表达式的计算结果不是常量。GCC编译时没有错误 这是MSVC编译器的错误吗? 是否有一个标准/聪明的解决方法来

以下工作如预期:

#include <array>
constexpr std::array<int, 3> values = {1, 2, 3};
template <int i> struct A { static constexpr int val = values[i]; };
int main() { A<1> a; }
错误是表达式的计算结果不是常量。GCC编译时没有错误

这是MSVC编译器的错误吗? 是否有一个标准/聪明的解决方法来规避此错误?
这实际上是GCC的错误/缺陷,而不是MSVC

A<values.size()> a;
导致您访问超出范围的值,因为有效索引为[0,size]。MSVC会给您一个错误,它无法执行此操作,因为这是未定义的行为,在常量表达式中不允许这样做


请注意,clang也能正确诊断并发出错误:

MSVC是正确的。在任何constexpr上下文中都不能有未定义的行为。否则,这不是一个常量表达式

该行:

int main() { A<values.size()> a; }
这超出了范围。事实上,MSVC正确地诊断了错误:

另一方面,GCC和MSVC都接受此代码:

int main() { A<values.size() - 1> a; }

MSVC的哪个版本?版本x64 MSVC v19.16,请看解决方法很简单,没有?int main{A;}顺便说一句,我可能会更改标题,这里没有单一的编译器错误,为什么会有另一个?我更改了标题。由于GCC编译,MSVC不编译,编译器错误?似乎合适。
constexpr auto i = values[values.size()];
example.cpp
<source>(3): error C2131: expression did not evaluate to a constant
C:/msvc/v19_16/include\array(187): note: failure was caused by out of range index 3; allowed range is 0 <= index < 3
<source>(4): note: see reference to class template instantiation 'A<3>' being compiled 
<source>(2): note: see reference to class template instantiation 'std::array<int,3>' being compiled
Compiler returned: 2
int main() { A<values.size() - 1> a; }