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
in foo
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).