But it compiles in gcc 4.9.0. See live example:
#include <iostream>
struct A {
constexpr A(): i(5) {}
int&& f() { return std::move(i); }
int i;
} a;
A&& f(A& a) { return std::move(a); }
int main() {
A a;
int b[a.f()]{ 0, 1, 2, 3, 4 };
std::cout << b[4] << '\n';
}
From §5.19/3 we have:
An integral constant expression is an expression of integral or unscoped enumeration type, implicitly converted to a prvalue, where the converted expression is a core constant expression. [ Note: Such expressions may be used as array bounds (8.3.4, 5.3.4), as bit-field lengths (9.6), as enumerator initializers if the underlying type is not fixed (7.2), and as alignments (7.6.2). —end note]
The expression a.f()
is an expression of integral type. It seems to me (although I need some clarification on this point) that this expression is also convertible to a prvalue, because it is an xvalue. But I think the real problem here is that the expression a.f()
is not a core constant expression, as it satisfies bullet point (2.1) in §5.19/2.
§5.19/2:
A conditional-expression
e
is a core constant expression unless the evaluation ofe
, following the rules of the abstract machine (1.9), would evaluate one of the following expressions:(2.1) —
this
(5.1.1), except in aconstexpr
function or a constexpr constructor that is being evaluated as part ofe
;
You're correct, a.f()
is not a constant expression. And variable length arrays are not allowed by the c++ standard. The GNU compiler, however, supports them as a language extension. You can ask the compiler to give you a warning when you use non-standard extensions with the -pedantic
option, or an error with -pedantic-errors
.
Edit: Apparently, GCC 4.9 added the official support for N3639, the proposal to add variable length arrays to the C++14 standard. In the end, the proposal was not included in the standard, but GCC 4.9 was released before C++14, so that change was not reflected. So, VLA's are supported by GCC 4.9 on purpose in C++14 mode and the above options don't disable them. Note that the C++14 mode is still experimental (even in GCC 5).
The following non-standard code
int x = std::rand();
int r[x] = { 1,2,3 };
compiles under g++, not because g++
mistakenly treats std::rand()
as a constant expression, but because it implements VLAs by default. Use -pedantic
or -Wvla
to warn about them, -Werror=vla
to turn these warnings into errors.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With