c++c++11overloadingrvalue-referencequalifiers

What's a use case for overloading member functions on reference qualifiers?


C++11 makes it possible to overload member functions based on reference qualifiers:

class Foo {
public:
  void f() &;   // for when *this is an lvalue
  void f() &&;  // for when *this is an rvalue
};

Foo obj;
obj.f();               // calls lvalue overload
std::move(obj).f();    // calls rvalue overload

I understand how this works, but what is a use case for it?

I see that N2819 proposed limiting most assignment operators in the standard library to lvalue targets (i.e., adding "&" reference qualifiers to assignment operators), but this was rejected. So that was a potential use case where the committee decided not to go with it. So, again, what is a reasonable use case?


Solution

  • In a class that provides reference-getters, ref-qualifier overloading can activate move semantics when extracting from an rvalue. E.g.:

    class some_class {
      huge_heavy_class hhc;
    public:
      huge_heavy_class& get() & {
        return hhc;
      }
      huge_heavy_class const& get() const& {
        return hhc;
      }
      huge_heavy_class&& get() && {
        return std::move(hhc);
      }
    };
    
    some_class factory();
    auto hhc = factory().get();
    

    This does seem like a lot of effort to invest only to have the shorter syntax

    auto hhc = factory().get();
    

    have the same effect as

    auto hhc = std::move(factory().get());
    

    The original proposal paper N1821 provides three motivating examples:

    1. Constraining operator = to lvalues (TemplateRex's answer)

    2. Enabling move for members (this answer)

    3. Constraining operator & to lvalues. I suppose this is sensible to ensure that the "pointee" is more likely to be alive when the "pointer" is eventually dereferenced:

       struct S {
         T operator &() &;
       };
      
       int main() {
         S foo;
         auto p1 = &foo;  // Ok
         auto p2 = &S();  // Error
       }
      

    Can't say I've ever personally used an operator& overload.