Boost :

Subject: Re: [boost] [operators] A modern SFINAE-based version of boost::operators?
From: Peter Dimov (lists_at_[hidden])
Date: 2017-11-15 16:05:41

For those interested, here's a test program with which you can play. The
results are, respectively, 0+1, 3+0, 0+3, 0+3, 0+0.

#include <iostream>
#include <utility>

int copies = 0;
int moves = 0;

struct T
{
int v_;

explicit T( int v ): v_( v ) {}
T( T const& t ): v_( t.v_ ) { ++copies; }
T( T&& t ): v_( t.v_ ) { ++moves; }

T& operator+=( T const& t ) { v_ += t.v_; return *this; }
};

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

/*
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
*/

/*
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
*/

/*
T operator+( T lhs, const T& rhs ) { lhs += rhs; return lhs; }
*/

/*
T operator+( T const & lhs, T const & rhs ) { return T( lhs.v_ + rhs.v_ ); }
*/

int main()
{
T t = T(1) + T(2) + T(3) + T(4);
std::cout << "T(" << t.v_ << "): " << copies << " copies, " << moves <<
" moves\n";
}