Reputation: 481
The following works as expected:
#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; }
However, I get a compiler error from the MSVC compiler if we use values.size()
as template parameter:
int main() { A<values.size()> a; }
The error is expression did not evaluate to a constant. The GCC compiles without error.
Upvotes: 0
Views: 187
Reputation: 41750
MSVC is right. There cannot be undefined behaviour in any constexpr context. Or else this is not a constant expression.
The line:
int main() { A<values.size()> a; }
Is basically:
constexpr auto i = values[values.size()];
Which is out of bound. In fact, MSVC correctly diagnose the error:
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
On the other hand, both GCC and MSVC accept this code:
int main() { A<values.size() - 1> a; }
Upvotes: 8
Reputation: 180415
This is actually a bug/flaw of GCC, not MSVC.
A<values.size()> a;
causes you to access values
out of range since the valid indexes are [0, size())
. MSVC gives you an error that it can't do that because it is undefined behavior, and that isn't allowed in a constant expression.
Note that clang also diagnoses this correctly and issues an error: https://godbolt.org/z/vmi86S
Upvotes: 3