C++11 - ref qualifiers
-
For non-static member functions, the type of the implicit object parameter is
— “lvalue reference to cv X” for functions declared without a ref-qualifier or with the & ref-qualifier
— “rvalue reference to cv X” for functions declared with the && ref-qualifier
where X is the class of which the function is a member and cv is the cv-qualification on the member function declaration.Wie habe ich das nun zu verstehen?
struct foo { void bar() // & { // *this ist foo&? } void bar() && { // *this ist nun foo&&? } };
Das wäre meiner Meinung nach unintuitiv, da die Derefernzierung eines Zeigers üblicherweise einen LValue zurückgibt. Hat man hier extra für this eine ausnahme gemacht?
Grüßle,
PI
-
Bzw, um die Frage nochmal zu erweitern: Falls ich das so richtig verstanden habe, wie siehts hier aus?
struct foo { void bar() && { foo* that = this; // *that foo&/foo&&? } };
-
Bitte beim Zitieren immer den Abschnitt angeben.
Dein Text findet sich in 13.3.1, hat also etwas mit Overloadauflösung zu tun.
Ein &&-ref-Qualifizierer führt nicht dazu, dass sich der Typ von Ausdrücken innerhalb einer solchen Funktion auf magische Weise ändert, *this ist immer ein lvalue.
-
Dann verstehe ich trotzdem nicht, was das in diesem Zusammenhang bedeutet.
-
#include <iostream> struct Foo { int bar() & {return 1;} int bar() && {return 2;} int bar() const& {return 3;} } Foo f(); int main() { Foo foo1; Foo const foo3; std::cout << foo1.bar(); //1 std::cout << f().bar(); //2 std::cout << foo3.bar(); //3 }
innerhalb der bar-Funktionen ist this immer ein lvalue, genauso wie z.B. im move-ctor das Argument zwar eine rvalue-Referenz ist, die Referenz aber dadurch, dass sie einen Namen hat, auch wieder ein lvalue ist. Es könnte aber z.B. in rref-qualifizierten Funktionen Sinn machen, an geeigneter Stelle sowas verrücktes wie
std::move(*this)
aufzurufen.
-
314159265358979 schrieb:
For non-static member functions, the type of the implicit object parameter is …
…
Die Rede ist vom Typ des Parameters. Bei
void foo(int && r) { r ist ein Lvalue }
kannst Du die Funktion zwar nur mit Rvalues aufrufen, innerhalb der Funktion ist r aber ein Lvalue. Genauso ist *this immer ein Lvalue.
314159265358979 schrieb:
struct foo { void bar() // & { // *this ist foo&? } void bar() && { // *this ist nun foo&&? } };
Diese Überladung ist auch nicht erlaubt. Wenn Du Ref-qualifier nutzen willst, musst Du sie jeder Überladung hinzufügen:
struct foo { void bar() const&; void bar() &&; };
Die Überladungsauflösung geschieht dann genauso wie bei folgenden Deklarationen:
void foo_bar(foo const& self); void foo_bar(foo && self);
Auch dort, innerhalb der Funktionskörper, wird self ein Lvalueausdruck sein.