Boost logo

Boost :

Subject: Re: [boost] [operators] What is the correct overload set for a binary operator?
From: Andrew Ho (helloworld922_at_[hidden])
Date: 2013-04-28 15:47:51


Daniel Frey <d.frey <at> gmx.de> writes:

> One remarks about the proposed full version of operators2.hpp: Andrew, I
really appreciate your work and
> enthusiasm, but please understand that IMHO this needs to be done step-by-
step and much more slowly than
> you probably hope for. Let's figure out the proper overload set for T+T
first, then T+U/U+T (again both
> commutative and non-commutative), noexpect-specifier for all overloads,
etc. After that, we need to
> decide on whether or not to improve the existing operator library or to
provide an independent V2. This
> might include rethinking the grouped templates. Using Boost.Move might
help with the implementation or
> not, depending on what overload set we want/need. It all needs tests and
documentation and it will be quite
> some work… hope you and others are still with me on this :)
>

That's fine, I was using that code as a test-bed to try and understand how
different features would fit together, and it really wasn't much work once I
had a cleaned-up base (I can re-use the same base with any
BOOST_BINARY_OPERATOR macro definition quite easily, some other changes may
be relatively easy to scale). I figured I might as well share my results to
demonstrate my findings (for example, I was curious as to how Boost Move
would fit in).

> Could someone please test this with VC++?

Yeah, I did some testing with VS2012 (/O2 optimizations) using your original
set and with Marc's set. Both work, but Marc's set does result in fewer
temporaries all-together. To be specific, all internal moves seem to be
optimized away, only move required is moving into the result variable. I
think this provides all of the benefits of your previous rvalue-ref code
without the unsafe behavior.

I got the same results testing with MinGW (GCC 4.7.2).

One interesting behavior I noticed while testing:

1)

MyClass operator+( const MyClass& lhs, const MyClass& rhs )
{
  MyClass nrv(lhs);
  nrv += rhs;
  return nrv;
}

2)

MyClass operator+( const MyClass& lhs, const MyClass& rhs )
{
  return std::move(MyClass(lhs) += rhs);
}

1) and 2) do not compile equivalently. 2) for some reason does not allow the
compiler to perform return value optimizations (at least the compilers I
tested with), potentially resulting in extra unnecessary temporaries.


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