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&&?
        }
    };
    

  • Mod

    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.


Log in to reply