class A { public: A() = default; ~A() = default; A(...">

Return "this" as rvalue

The following code, as expected, does not compile

#include <iostream> class A { public: A() = default; ~A() = default; A(const A&) = delete; A(A&&) = delete; A& operator=(const A&) = delete; A& operator=(A&&) = delete; A& operator<<(const int i) { std::cout << "operator<< called" << std::endl; return *this; } }; void foo(A&& a) { std::cout << "foo called" << std::endl; } int main() { A a; a << 14; foo(std::move(a)); // works fine foo(A() << 14); // does not compile return 0; } 

Change class A to

 class A { public: A() = default; ~A() = default; A(const A&) = delete; A(A&&) = delete; A& operator=(const A&) = delete; A& operator=(A&&) = delete; A& operator<<(const int i) & { std::cout << "operator<< called on lvalue" << std::endl; return *this; } A&& operator<<(const int i) && { std::cout << "operator<< called on rvalue" << std::endl; return std::move(*this); } }; 

does compilation of the program. However, returning values ​​with std :: move is usually not a good idea, as it will return broken links or prevent the compiler from performing certain optimizations.

Is the described case one of the few exceptions to the thumb rule "do not return by rvalue" or should the problem be solved in different ways?

Many thanks!

+5
source share
1 answer

This code is absolutely correct and safe. Since your object is already an rvalue in

 A&& operator<<(const int i) && 

adding the rvalue value again (with moving) does not change the security of the code. Optimization of NRVO will not take place in this case, so the code speed is unlikely to be affected.

So, as you formulate it, I would say "yes, this is an exception to the rule"

Also, this rule is not universal: if you understand what is happening (which is why you asked this question), you can rely on your common sense, and not on it.

0
source

All Articles