2015-12-20 16 views
7

Ale kompiluje się w gcc 4.9.0. Zobacz live example:O ile wiem, ten kod nie powinien się kompilować, zgodnie z §5.19/3 i §5.19/2 w 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'; 
} 

Od §5.19/3 mamy:

Integralną stała ekspresja jest wyrazem integralną lub unscoped typu wyliczenia, niejawnie konwertowane na prvalue, gdzie przekonwertowany wyrażenie jest stałym wyrażeniem stałym. [Uwaga: Takie wyrażenia mogą być używane jako ograniczenia tablicowe (8.3.4, 5.3.4), jako pola bitowe długości (9.6), jako inicjatory modułów wykonawczych, jeśli typ bazowy to , nie ustalony (7.2), oraz jako wyrównania (7.6.2). -end note]

Wyrażenie a.f() jest wyrażeniem typu całkowego. Wydaje mi się (choć potrzebuję wyjaśnienia na ten temat), że wyrażenie to można również przekształcić na wartość, ponieważ jest to wartość x. Ale myślę, że prawdziwym problemem jest to, że wyrażenie a.f() jest rdzennym wyrażeniem stałym, ponieważ spełnia punktor punktowy (2.1) w §5.19/2.

§5.19/2:

Warunkowe ekspresja e jest rdzeń stałym wyrażeniem ile oceny e, kierując się zasadami abstrakcyjnej maszynie (1.9), by ocenić jedną z następujących wyrażenia:

(2,1) - this (5.1.1), z wyjątkiem funkcji constexpr lub konstruktora constexpr, który jest przetwarzany w ramach e;

+1

Jeśli spróbujesz skompilować to z kodem ++, to wskazuje, że "tablice o zmiennych rozmiarach są niedozwolone" - więc mam wrażenie, że gcc po prostu nie jest wystarczająco pedantyczny. –

+0

Przekonanie GCC do egzekwowania zgodności może być uciążliwe. Stwierdziłem, że kompilowanie z flagą '--pedantic-errors' wydaje się działać. Preferuję ścisłą zgodność jako domyślną i flagi do wyłączenia zgodności. – Galik

+0

Czy ta witryna włącza ścisły tryb zgodności w kompilatorze (jestem zbyt leniwy, aby dowiedzieć się, jakie skrypty/witryny stron trzecich umożliwiają zobaczenie tego dla siebie)? Jeśli nie, powodem jest to, że g ++ ma niestandardowe rozszerzenie dla macierzy czasu automatycznego przechowywania o niestałym rozmiarze. – celtschk

Odpowiedz

7

Masz rację, a.f() nie jest wyrażeniem stałym. A tablice o zmiennej długości nie są dozwolone przez standard C++. Jednak kompilator GNU obsługuje je jako language extension. Możesz poprosić kompilator o ostrzeżenie, gdy używasz niestandardowych rozszerzeń z -pedantic option lub błędu z -pedantic-errors.

Edycja: Podobno GCC 4.9 added oficjalne wsparcie dla N3639, propozycja dodania tablic o zmiennej długości do standardu C++ 14. Ostatecznie propozycja nie została uwzględniona w standardzie, ale GCC 4.9 została wydana przed C++ 14, więc zmiana nie została odzwierciedlona. Tak więc, VLA są obsługiwane przez GCC 4.9 celowo w trybie C++ 14, a powyższe opcje nie wyłączają ich. Zauważ, że tryb C++ 14 jest wciąż eksperymentalny (nawet w GCC 5).

+0

Nie ma komunikatów o błędach z '-pedantic-errors', ani ostrzeżeń z' -pedantic' – Ayrosa

+0

Czy powiedziałbyś, że jest to również tablica o zmiennej długości? 'struct A {operator int() {return 5; }} a; int main() {int b [a] {0, 1, 2, 3, 4}; } ' – Ayrosa

+1

@Ayrosa hmm, wypróbowałem to i najwyraźniej nie ma ostrzeżenia/błędu podczas kompilacji z' -std = C++ 14' przy użyciu g ++ - 4.9.2, ale jest tam, gdy skompilowane z '-std = c + + 11'. Ostrzeżenie działa w języku C++ 14 z g ++ - 5.2.0. Może to być błąd kompilatora i najwyraźniej został naprawiony. – user2079303

2

Poniższa, standardowy kod

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

zestawia trybie g ++ nie ponieważ g++ błędnie traktuje std::rand() postaci stałej ekspresji, ale ponieważ realizuje vlas domyślnie. Użyj -pedantic lub -Wvla, aby ostrzec o nich, -Werror=vla, aby zamienić te ostrzeżenia w błędy.

+1

Jednak błąd nie pojawia się, gdy używam '-pedantic' w powyższym kodzie. – Ayrosa

+1

@Ayrosa Być może dlatego, że 4.9 jest stosunkowo stary. Pokazuje się w 5.2. –

+0

Jeśli zmienię funkcję 'f' na' constexpr' w powyższym kodzie, '5.2' dalej pokazuje błąd, ale teraz uważam, że kod jest legalny, z powodu §5.19/2 i §5.19/3. – Ayrosa