TryMe::arr
è odr-used ma non si fornisce una definizione (see it live):
constexpr int TryMe::arr[1];
Perché è il risultato incoerenti tra gcc
e clang
? Questo perché le violazioni ODR non richiedono una disagnostic, sia dal C++ 11 e C++ 14 progetto di norma (sottolineatura mia):
Ogni programma deve contenere esattamente una definizione di ogni non-inline funzione o variabile che è odr-usata in quel programma; non è richiesta la diagnosi .
Lo possiamo vedere è ODR-usato dal progetto di 11 standard di C++, sezione 3.2
che dice:
Un'espressione è potenzialmente valutata a meno che non si tratta di un non valutata operando (clausola 5) o una sottoespressione di ciò. Una variabile il cui nome appare come un'espressione potenzialmente valutata è odr-used a meno che non sia un oggetto che soddisfi i requisiti per apparire in un'espressione costante (5.19) e la conversione lvalue-rvalue (4.1) sia immediatamente applicato.
TryMe::arr
è un oggetto e lo fa soddisfare i requisiti per essere apparso in un'espressione costante ma la conversione lvalue a rvalue non viene immediatamente applicato al TryMe::arr
ma TryMe::arr[0]
.
La formulazione aggiornata dal progetto di C++ 14 standard che si applica al C++ 11 così da quando è stato applicato tramite un rapporto difetti (DR 712):
A x variabile il cui nome appare come un'espressione potenzialmente valutata ex è odr-used a meno che non si applichi la conversione da lvalue a rvalue (4.1) a xa x restituisce un'espressione costante (5.19) che non richiama alcuna funzione non banale e, se x è un oggetto, ex è un elemento del set di potenziali risultati di un'espressione e, dove sia lo lvalue-to-rvalue conversione (4.1) viene applicato e, oppure e è un'espressione scartato valore
I potenziali risultati dell'espressione TryMe::arr[0]
è vuota dai criteri di 3.2
punto 2
e così è odr-usato.
Nota: è necessario fornire una definizione al di fuori della classe di cui al punto 9.4.2
[class.static.data] che dice (sottolineatura mia):
un membro di dati statici di letterali il tipo può essere dichiarato nella classe definizione con lo specificatore constexpr; in tal caso, la sua dichiarazione deve specificare un inizializzatore di coppia o uguale in cui ogni clausola di inizializzazione che è un'espressione di assegnazione è un'espressione costante. [Nota: nel entrambi questi casi, il membro può apparire in espressioni costanti. -end nota] L'utente deve ancora essere definito in un ambito namespace se è ODR-utilizzato (3.2) nel programma e la definizione dello spazio dei nomi ambito non devono contenere un inizializzatore
Aggiornamento
TC sottolineato defect report 1926 che aggiunge la seguente proiettile 3.2
[basic.def.odr] paragrafo 2:
- se E è un'operazione di indicizzazione (5.2.1 [expr.sub]) con un operando matrice, la set contiene quell'operando.
che significa indicizzazione di un array non è più un ODR uso e quindi il codice PO sarebbe ben formata in 1Z C++ e sembra C++ 14 poiché il difetto sembra che sia contro C++ 14.
Quale versione di clang? –
Quello sul coliru – Dean
funziona bene per me: http://coliru.stacked-crooked.com/a/2b319b9351784244 Hai attivato il flag 'C++ 11'? – texasbruce