Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

As far as I can tell, this code should not compile, according to §5.19/3 and §5.19/2 in C++14

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 of e, following the rules of the abstract machine (1.9), would evaluate one of the following expressions:

(2.1) — this (5.1.1), except in a constexpr function or a constexpr constructor that is being evaluated as part of e;

like image 426
Ayrosa Avatar asked Dec 20 '15 13:12

Ayrosa


2 Answers

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).

like image 161
eerorika Avatar answered Nov 01 '22 04:11

eerorika


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.

like image 24
n. 1.8e9-where's-my-share m. Avatar answered Nov 01 '22 06:11

n. 1.8e9-where's-my-share m.