Betrachten Sie das folgende Beispiel ( Snippet (0) ):
struct X
{
constexpr int get() const { return 0; }
};
void foo(const X& x)
{
constexpr int i = x.get();
}
int main()
{
foo(X{});
}
Das obige Beispiel wird mit allen Versionen von g++
vor g++ 10.x
und nie unter kompiliert clang++
. Die Fehlermeldung lautet:
error: 'x' is not a constant expression 8 | constexpr int i = x.get(); |
Der Fehler macht Sinn, da er x
niemals ein konstanter Ausdruck im Körper ist von foo
:
X::get()
ist markiertconstexpr
und hängt nicht vom Zustand abx
;Durch Ändern
const X&
vonconst X
wird der Code mit jedem Compiler- Snippet ( auf godbolt.org) kompiliert (1) .
Noch interessanter wird es, wenn ich X::get()
als static
( (auf godbolt.org) Snippet (2) ) markiere . Mit dieser Änderung werden alle getesteten Versionen g++
(einschließlich Trunk) kompiliert, während sie clang++
immer noch nicht kompiliert werden können.
Also meine Fragen:
Ist es
g++ 9.x
richtig, Snippet (0) zu akzeptieren ?Sind alle Compiler korrekt darin, Snippet (1) zu akzeptieren ? Wenn ja, warum ist die Referenz von Bedeutung?
Sind
g++ 9.x
undg++ trunk
richtig in der Annahme von Snippet (2) ?
x
infoo
ist kein konstanter Ausdruck. Es gibt sogar einen alten (informell abgelehnten) Fehlerbericht über Clang wegen seines korrekten Verhaltens (während GCC einen tatsächlichen Fehler dafür hatte).Antworten:
Nein.
Ja, sind Sie.
Ein konstanter Ausdruck kann keinen ID-Ausdruck verwenden, der eine Referenz benennt, die keine vorherige Initialisierung eines konstanten Ausdrucks hat oder deren Lebensdauer während der Auswertung des konstanten Ausdrucks begonnen hat. [expr.const] /2.11 ( dasselbe in C ++ 20 )
Das Gleiche gilt nicht, wenn Sie eine Nichtreferenzvariable benennen, ohne dass eine Konvertierung von lWert in rWert erforderlich ist.
x.get()
wird nurx
als lvalue bezeichnet und ruft nur eineconstexpr
Funktion auf, die tatsächlich auf kein Mitglied von zugreiftx
, sodass kein Problem vorliegt .Nein, da der Ausdruck immer noch den Unterausdruck enthält, der
x
gegen die oben genannte Regel verstößt.quelle