Boost logo

Boost :

Subject: Re: [boost] [operators] A modern SFINAE-based version of boost::operators?
From: Gavin Lambert (gavinl_at_[hidden])
Date: 2017-11-14 23:04:15


On 15/11/2017 07:16, Daniel Frey wrote:
> Before looking at those cases, consider a commutative operator+ (abbreviated version):
>
> T operator+( const T& lhs, const T& rhs ) { T nrv( lhs ); nrv += rhs; return nrv; } // v1
> T&& operator+( T&& lhs, const T& rhs ) { lhs += rhs; return std::move( lhs ); } // v2
> T&& operator+( const T& lhs, T&& rhs ) { rhs += lhs; return std::move( rhs ); } // v3, remember: we assume a commutative +
> T&& operator+( T&& lhs, T&& rhs ) { lhs += rhs; return std::move( lhs ); } // v4

Given that NRVO is mandatory now, isn't it just as efficient and more
correct to declare these as:

T operator+( const T& lhs, const T& rhs ) { T nrv( lhs ); nrv += rhs;
return nrv; } // v1
T operator+( T&& lhs, const T& rhs ) { lhs += rhs; return lhs; }
// v2
T operator+( const T& lhs, T&& rhs ) { rhs += lhs; return rhs; }
// v3, remember: we assume a commutative +
T operator+( T&& lhs, T&& rhs ) { lhs += rhs; return lhs; }
// v4

(You could save a little typing by using "return lhs += rhs;" but that's
probably not a good idea as you're left to the whims of compiler
inlining whether it triggers some kind of RVO or not.)

Unless I'm missing something?

> a) Explicitly binding to a reference "to prolong the lifetime of the temporary".
>
> This happens if you write
>
> const T& t = t1 + ( t2 + t3 ) + t4;
>
> As the last operator+ return an rvalue reference instead of an rvalue, the "const T& t =" does not bind to a temporary. The intermediate temporary created by (v2+v3) is destroyed at the end of the expression, hence t is now a dangling reference. Oops.

The above would fix this, and your other case.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk