Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 812
KnowItAllWannabe Avatar asked Jan 10 '14 19:01

KnowItAllWannabe


People also ask

What is the use of function overloading?

Overloaded functions enable you to supply different semantics for a function, depending on the types and number of its arguments. For example, consider a print function that takes a std::string argument. This function might perform very different tasks than a function that takes an argument of type double .

Which operators can be overloaded only as member functions?

Operators which can be overloaded either as members or as non-members. This is the bulk of the operators: The pre- and post-increment/-decrement operator++() , operator--() , operator++(int) , operator--(int) The [unary] dereference operator*()

Can we overload operator using member function as well as friend function?

When binary operators are overloaded through a member function they take one explicit argument. If overloaded through a friend function they instead take two explicit arguments. We do not use friend functions to overload some specific operators. However, member functions can be used to overload them.

When functions are overloaded which part of the functions are the same?

Function overloading is a feature that allows us to have same function more than once in a program. Overloaded functions have same name but their signature must be different.


2 Answers

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()); 

EDIT: I found the original proposal paper, it provides three motivating examples:

  1. Constraining operator = to lvalues (TemplateRex's answer)
  2. Enabling move for members (basically 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.

like image 99
Casey Avatar answered Sep 21 '22 09:09

Casey


One use case is to prohibit assignment to temporaries

 // can only be used with lvalues  T& operator*=(T const& other) & { /* ... */ return *this; }    // not possible to do (a * b) = c;  T operator*(T const& lhs, T const& rhs) { return lhs *= rhs; } 

whereas not using the reference qualifier would leave you the choice between two bads

       T operator*(T const& lhs, T const& rhs); // can be used on rvalues  const T operator*(T const& lhs, T const& rhs); // inhibits move semantics 

The first choice allows move semantics, but acts differently on user-defined types than on builtins (doesn't do as the ints do). The second choice would stop the assigment but eliminate move semantics (possible performance hit for e.g. matrix multiplication).

The links by @dyp in the comments also provide an extended discussion on using the other (&&) overload, which can be useful if you want to assign to (either lvalue or rvalue) references.

like image 26
TemplateRex Avatar answered Sep 19 '22 09:09

TemplateRex