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.xund 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 xniemals ein konstanter Ausdruck im Körper ist von foo:
X::get()ist markiertconstexprund hängt nicht vom Zustand abx;Durch Ändern
const X&vonconst Xwird 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.xrichtig, Snippet (0) zu akzeptieren ?Sind alle Compiler korrekt darin, Snippet (1) zu akzeptieren ? Wenn ja, warum ist die Referenz von Bedeutung?
Sind
g++ 9.xundg++ trunkrichtig in der Annahme von Snippet (2) ?
xin fooist 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).