DR 712 war verantwortlich für die Änderung des Wortlauts von [basic.def.odr] / 2 in C ++ 11 zum heutigen Wortlaut in [basic .defodr] 2 und 3 . Aber ich versuche immer noch, den Grund für die Änderung zu verstehen, wie in der DR gesagt:
712. Sind Integer-Konstantenoperanden eines Bedingungsausdrucks "verwendet?"
Bei der Beschreibung von statischen Datenelementen, die in der Klasse initialisiert wurden Definition, 9.2.3.2 [class.static.data] Absatz 3 sagt,
Das Element sollte weiterhin in einem Namensraumbereich definiert sein, wenn es verwendet wird im Programm ...
Die Definition von "used" ist in 3.2 [basic.defodr] Absatz 1:
Ein Objekt oder eine nicht überladene Funktion, deren name erscheint als potenziell evaluiertes
Ausdruck wird verwendet, es sei denn, es ist ein Objekt, das die Anforderungen für das Erscheinen in a erfüllt konstanter Ausdruck (5.20 [expr.const]) und die lvalue-to-rvalue-Konvertierung (4.1 [conv.lval])
wird sofort angewendet.Betrachten Sie nun das folgende Beispiel:
%Vor%Nach dem aktuellen Wortlaut des Standards, diesem Beispiel erfordert, dass
S::a
undS::b
in einem Namensraumbereich definiert sind. Das Grund dafür ist, dass gemäß 5.16 [Ausdr.] Absatz 4 Das Ergebnis dieses bedingten Ausdrucks ist ein Lvalue und der Lvalue-to-rvalue-Konvertierung wird auf das angewendet, nicht direkt auf das Objekt, , damit die Anforderung "sofort angewendet" nicht erfüllt wird . Das ist überraschend und unglücklich, da nur die Werte und nicht die Adressen der statischen Datenmitglieder werden verwendet. (Dieses Problem auch gilt für den vorgeschlagenen Beschluss zu Frage 696.)
Nun, wenn die "sofort angewendete Anforderung fehlschlägt, dann werden die Ausdrücke S::a
und S::b
im bedingten Ausdruck nicht verwendet (odr-used), und so die jeweiligen statischen Member von struct S
wird nicht im Namespace-Bereich definiert sein, aber das ist genau das Gegenteil dessen, was die DR sagt. Was fehlt mir ???
Ich denke, du verpasst den Punkt der used
-Definition:
Also, wenn "sofort angewendet" ist falsch, dann ist die UNLESS ist falsch, und damit wird es verwendet.
Ein Objekt oder eine nicht überladene Funktion, deren Name als potenziell ausgewerteter Ausdruck erscheint, wird verwendet, es sei denn, [...]
Nun, S::a
und S::b
erscheinen in einem potenziell ausgewerteten Ausdruck in f
.
Sie werden also verwendet, sofern keine der folgenden Ausnahmen zutrifft.
[...] es ist ein Objekt, das die Anforderungen erfüllt, um in einem konstanten Ausdruck zu erscheinen (5.20 [expr.const]) und die lvalue-to-rvalue-Konvertierung (4.1 [conv.lval]) wird sofort angewendet.
Nun, es ist ein Objekt, das die Anforderung erfüllte, in einem konstanten Ausdruck zu erscheinen. Also besteht es diesen Test.
Aber die Lvalue-to-rvalue-Konvertierung wird nicht sofort angewendet.
Also versagt dieser Test.
Da dieser gesamte Abschnitt unter "es sei denn" steht, bedeutet der Fehler, dass der vorherige Fall zutrifft; das Objekt wird als "gebraucht" betrachtet.
Tags und Links c++ c++11 language-lawyer c++17 one-definition-rule