TryMe::arr
jest odr-used ale nie zawiera definicji (see it live):
constexpr int TryMe::arr[1];
Dlaczego wynik niezgodny między gcc
i clang
? To dlatego, że naruszanie ODR nie wymagają disagnostic, zarówno z projektu standardu C++ 11 i C++ 14 (nacisk kopalni):
Każdy program zawiera dokładnie jedną definicję każdej non-inline funkcja lub zmienna, która jest odr używana w tym programie; brak diagnostyki wymagane.
Możemy to zobaczyć jest odr używane z projektu C++ standardowe 11, sekcja 3.2
który mówi:
Wyrażenie jest potencjalnie ocenić, chyba że jest to unevaluated operand (punkt 5) lub jego podwyrażenie. Zmienna, której nazwa pojawia się jako potencjalnie oszacowany wyrażenie, jest używana odr, chyba że jest to obiekt spełniający wymagania dla pojawiania się w stałej ekspresji (5.19), a konwersja l-wartość-do-r (4.1) jest natychmiastowa. stosowany.
TryMe::arr
Przedmiotem i spełnia wymagania na pojawiające się w stałej ekspresji, ale konwersja lwartość do RValue nie jest natychmiast stosowany do TryMe::arr
ale TryMe::arr[0]
.
Zaktualizowana treść od standardu w Projekty C++ 14, który odnosi się do C++ 11, a ponieważ była ona stosowana poprzez raportu defektami (DR 712):
zmiennej x, której nazwisko pojawia się jako potencjalnie oszacowaną ekspresję jest odr-stosowane, chyba że zastosowanie konwersji wartości l do (r) (4.1) na x daje stałą ekspresję (5.19), która nie wywołuje żadnych niebanalnych funkcji i, jeśli x jest object, ex jest elementem zestawu potencjalnych wyników wyrażenia e, gdzie albo lwartość do RValue konwersji (4.1) stosuje się do E lub E jest wyrażeniem odrzucono wartość
W potencjalne wyniki ekspresji TryMe::arr[0]
jest pusta kryteriami w 3.2
ust 2
itd jest używany odr.
Uwaga: należy podać definicję poza klasą, jak na odcinku 9.4.2
[class.static.data] który mówi (podkr):
Statyczny członek danych dosłowny typ można zadeklarować w definicji klasy ze specyfikatorem constexpr; jeśli tak, jego deklaracja powinna określać inicjator klamrowy lub równy, w którym każda inicjująca klauzula , która jest ekspresją przypisania, jest wyrażeniem stałym. [Uwaga: W obu tych przypadkach element może pojawiać się w wyrażeniach stałych. -end uwaga] Członek zostaje jeszcze zdefiniowane w zakresie przestrzeni nazw, jeśli jest odr wykorzystane (3.2) w programie oraz definicję zakresu nazw nie zawierają inicjator
Aktualizacja
TC wskazał defect report 1926 który dodaje się następujące pocisk 3.2
[basic.def.odr] Punkt 2:
- gdy E oznacza działanie indeksowanie (5.2.1 [expr.sub]) o operandzie tablicy, zestaw zawiera ten operand.
Czyli indeksowanie tablicy nie jest już ODR-use a więc kod OP będzie dobrze uformowane w C++ 1z i wydaje się, że C++ 14, ponieważ wada to wygląda przeciwko C++ 14.
Która wersja clang? –
Ten na coliru – Dean
Działa dobrze dla mnie: http://coliru.stacked-crooked.com/a/2b319b9351784244 Czy włączono 'flaga C++ 11'? – texasbruce