2015-12-20 10 views
7

ma compila in gcc 4.9.0. Vedere live example:Per quanto posso dire, questo codice non dovrebbe essere compilato, in base a §5.19/3 e § 5.19/2 in C++ 14

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

Da §5.19/3 abbiamo:

Un'espressione costante intera è un'espressione integrale o tipo di enumerazione senza ambito, implicitamente convertito in un prvalue, dove convertito espressione è un'espressione costante di base. [Nota: Tali espressioni possono essere utilizzate come limiti di array (8.3.4, 5.3.4), come lunghezza del campo di bit (9.6), come inizializzatori di enumeratori se il tipo sottostante è non riparato (7.2) e come allineamenti (7.6.2). -end note]

L'espressione a.f() è un'espressione di tipo integrale. Mi sembra (anche se ho bisogno di chiarimenti su questo punto) che questa espressione sia anche convertibile in un valore, perché è un valore x. Ma penso che il vero problema qui è che l'espressione a.f() è non un'espressione costante di nucleo, in quanto soddisfa punto elenco (2.1) in § 5.19/2.

§5.19/2:

A condizionale espressione e è un nucleo espressione costante a meno che la valutazione di e, seguendo le regole della macchina astratta (1.9), sarebbe valutare una delle seguenti espressioni:

(2.1) - this (5.1.1), eccetto in una funzione constexpr o un costruttore constexpr che viene valutato come parte di e;

+1

Se si prova a compilarlo con clang ++, si sottolinea che "gli array di dimensioni variabili non sono consentiti", quindi ho la sensazione che gcc non sia abbastanza pedante. –

+0

Convincere GCC per far rispettare la conformità può essere un dolore. Ho trovato la compilazione con il flag '--pedantic-errors' sembra fare il trucco. Preferirei la stretta conformità come default e le bandiere per disattivare la conformità. – Galik

+0

Questo sito abilita la modalità di conformità rigorosa sul compilatore (sono troppo pigro per capire quali script/siti di terze parti abilitare a vederlo da solo)? In caso contrario, il motivo è che g ++ ha un'estensione non standard per gli array di durata della memorizzazione automatica con dimensioni non costanti. – celtschk

risposta

7

Sei corretto, a.f() non è un'espressione costante. E gli array di lunghezza variabile non sono consentiti dallo standard C++. Il compilatore GNU, tuttavia, li supporta come language extension. È possibile chiedere al compilatore di fornire un avviso quando si utilizzano estensioni non standard con lo -pedantic option o un errore con -pedantic-errors.

Modifica: Apparentemente, GCC 4.9 added il supporto ufficiale per N3639, la proposta di aggiungere matrici di lunghezza variabile allo standard C++ 14. Alla fine, la proposta non è stata inclusa nello standard, ma GCC 4.9 è stato rilasciato prima di C++ 14, in modo che la modifica non fosse riflessa. Quindi, i VLA sono supportati da GCC 4.9 di proposito in modalità C++ 14 e le opzioni di cui sopra non li disabilitano. Si noti che la modalità C++ 14 è ancora sperimentale (anche in GCC 5).

+0

Non ci sono messaggi di errore con '-pedantic-errors', né avvisi con' -pedantic' – Ayrosa

+0

Diresti che questa è anche una matrice di lunghezza variabile? 'struct A {operator int() {return 5; }} a; int main() {int b [a] {0, 1, 2, 3, 4}; } ' – Ayrosa

+1

@Ayrosa hmm, l'ho provato e apparentemente non c'è nessun avviso/errore quando compilato con' -std = C++ 14' usando g ++ - 4.9.2, ma c'è quando è compilato con '-std = c + + 11'. L'avviso funziona in C++ 14 con g ++ - 5.2.0. Questo potrebbe essere un bug del compilatore e apparentemente risolto. – user2079303

2

Il codice non standard seguente

int x = std::rand(); 
int r[x] = { 1,2,3 }; 

compila sotto g ++, non perché g++ tratta i erroneamente std::rand() come un'espressione costante, ma perché implementa VLA di default. Utilizzare -pedantic o -Wvla per avvisare su di loro, -Werror=vla per trasformare questi avvisi in errori.

+1

Tuttavia, l'errore non viene visualizzato quando uso '-pedantic' nel mio codice qui sopra. – Ayrosa

+1

@Ayrosa Forse perché il 4.9 è relativamente vecchio. Lo mostra in 5.2. –

+0

Se cambio la funzione 'f' in' constexpr' nel mio codice sopra, '5.2' mostra ancora un errore, ma ora credo che il codice sia legale, a causa di §5.19/2 e §5.19/3. – Ayrosa