2015-12-21 14 views
15

Pierwszy fragment zestawia bez ostrzeżeń (live example)Dlaczego te fragmenty są inaczej obsługiwane przez GCC?

#include <iostream> 

struct A { 
    constexpr A(): i(5){} 
    constexpr operator int() { return 5; } 
    int i; 
}; 

int main() { 
    A a; 
    int b[a]{ 0, 1, 2, 3, 4 }; 
    std::cout << b[4] << '\n'; 
} 

teraz zmieniać powyższy fragment powracając i w operatorze konwersji (live example):

constexpr operator int() { return i; } 

GCC ostrzega b jest VLA .

Dla mnie oba warianty wydają się być zgodne z paragrafem § 5.19 [wyrażenie.konst.]/3 w C++ 14.

Odpowiedz

17

Ty wykonywania konwersji ltr na i, ale [expr.const]/(2,7) nie może być naruszone tutaj, (2.7.3) muszą być stosowane:

enter image description here

(2.7.1) dotyczy obiektów pełnych, (2.7.2) mówi o literałach ciągów znaków i (2.7.4) dotyczy obiektów, których okres istnienia rozpoczął się w ramach oceny wyrażenia - niestosowanie od a deklaracji poprzedza b.

Zdefiniuj a jako constexpr, a kod jest zgodny.


Nieco dodatek w celu wyjaśnienia, co standardowe mówi: Ekspresja w nawiasie musi być przekształcony stałej ekspresji typu std::size_t ([dcl.array]/1), który jest określony w [expr.const]/4 jak

przekształcany stała ekspresja typuT jest wyrażeniem, niejawnie przekonwertowanym na typ T, gdzie przekształcone wyrażenie jest wyrażeniem stałym i [... wymaganiami, które są spełnione ...]

Tak więc, naprawdę, standardem jest zainteresowany, czy nie

constexpr std::size_t s = a; 

byłoby ważne. Co nie jest, z wyżej wymienionych powodów - próbą użycia podobiektu wcześniej zdefiniowanego, nie-constexpr obiektu.

+0

Dlaczego "a" musi w tym przypadku zostać poddane konwersji L-Value-to-R? Pytam o to, ponieważ definicja "przekonwertowanego wyrażenia stałego" w §5.19/3 (N4140) nie wymaga takiej konwersji z "a" w deklaracji 'int b [a] {0, 1 , 2, 3, 4}; '. – Ayrosa

+0

@Ayrosa Cóż, 'a' nigdy nie musi podlegać jednemu, ale musi zostać wywołany operator konwersji, aby przekonwertować go na' std :: size_t'. ('a' jest skonwertowanym wyrażeniem stałym typu' std :: size_t' wewnątrz nawiasów) – Columbo

+1

Zajęło mi trochę czasu, aby naprawdę zrozumieć, co powiedziałeś i podświetliłeś w swojej odpowiedzi.Zdecydowanie nie jest to łatwe zadanie dla pełnego zrozumienia Standardu. Świetna odpowiedź (+1). – Ayrosa

4

Rozmiar tablic musi być stałymi w czasie kompilacji, ale w drugim przykładzie inicjowanie A::i nie nastąpi przed wykonaniem.

+0

'A :: A()' jest 'constexpr' chociaż ... – YSC

+0

@YSC Tak, ale zmienna' a' w funkcji 'main' nie jest. –

+1

A * to * jest prawdziwym źródłem ostrzeżeń, prawda? – YSC

Powiązane problemy