Boost logo

Boost :

Subject: [boost] [operators] The future of Boost.Operators
From: Daniel Frey (d.frey_at_[hidden])
Date: 2013-04-22 15:43:00


Hello,

for a long time there hasn't been any significant update of Boost.Operators and I had an easy job being its maintainer for the past 10+ years. I guess that will change soon. :)

I would like to discuss the future of Boost.Operators, as several issues and options have piled up in the past. Here are some points to take into account:

1) Support for rvalue references to generate fewer temporaries. (where available)
2) Support for noexcept. (where available)
3) Support for constexpr if this is applicable at all. I haven't found the time to properly research it yet.
4) Allow dedicated commutative and non-commutative versions for several operators, leading to fewer temporaries for commutative versions in several cases.
5) Remove work-arounds for ancient compilers, general cleanup.

I worked on a clean rewrite (called df.operators) which supports 1), 2) and 4) (and obviously 5)) and published it a few weeks ago on GitHub, see <http://github.org/d-frey/operators/>. It is meant to show one option, but it is not a suitable replacement for Boost.Operators in its current form. If it turns out to be useful as a test-bed for the next version of Boost.Operators, I will be glad to improve it into this direction but the future of Boost.Operators does not depend on it. That said, I'd like to invite anyone interested to have a look. If applicable to the future of Boost.Operators, please provide feedback on this mailing list. If feedback only concerns df.operators but not Boost, please don't spam the list and write to my private email, thanks!

Some issues which need to be discussed/solved for Boost.Operators' future:

1.1) Which implementation should be used for maximum performance/compatibility?
1.1.1) Pass-By-Value as suggested by Dave Abrahams' article. (<http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/>)
1.1.2) Overloads for Pass-By-Const-LValue-Reference and Pass-By-RValue-Reference. (as in df.operators)

See below for why I decided to create 1.1.2) as an alternative to 1.1.1).

4.1) Decide for a default.
4.1.1) Commutative by default (as the current version of Boost.Operators assumes), non-commutative if explicitly requested by the user.
4.1.2) Non-commutative per default, commutative versions need to be explicitly requested by the user. (as in df.operators)

5.1) The main issue is probably the base-class-chaining.
5.1.1) Keep base-class-chaining, makes VC++ happy. (apply EBO and keep the object size small)
5.1.2) Drop base-class-chaining, stop punishing the rest of the world for VC++'s inability to apply the EBO for multiple inheritance. (I might be a bit biased here…)
5.1.3) Any other option I fail to see?

(If a MS-employee would like to provide some information on if/when the EBO-problem will be fixed (here or in private email), I'd be grateful. If it is already fixed, I apologize, but the last information I got about VS2012 suggests EBO is not applied for multiple inheritance.)

I think this should be enough to get some discussion going…

Best regards,
Daniel

Why 1.1.2) as an alternative to 1.1.1)? Consider the following test program:

#include <iostream>
#include <utility>

struct A
{
  A() { std::cout << "A::A()" << std::endl; }
  A( const A& ) { std::cout << "A::A(const A&)" << std::endl; }
  A( A&& ) { std::cout << "A::A(A&&)" << std::endl; }
  ~A() { std::cout << "A::~A()" << std::endl; }

  A& operator+=( const A& ) { std::cout << "+=" << std::endl; return *this; }
};

// #define BY_VALUE
#ifdef BY_VALUE
A operator+( A lhs, const A& rhs )
{
  lhs += rhs;
  return lhs;
}
#else
A operator+( const A& lhs, const A& rhs )
{
  A nrv( lhs );
  nrv += rhs;
  return nrv;
}

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

int main()
{
  A a, b, c, d;
  A r = a + b + c + d;
}

The above code, compiled with G++ or Clang prints:

A::A()
A::A()
A::A()
A::A()
A::A(const A&)
+=
+=
+=
A::A(A&&)
A::~A()
A::~A()
A::~A()
A::~A()
A::~A()
A::~A()

If you define BY_VALUE, it prints:

A::A()
A::A()
A::A()
A::A()
A::A(const A&)
+=
A::A(A&&)
+=
A::A(A&&)
+=
A::A(A&&)
A::~A()
A::~A()
A::~A()
A::~A()
A::~A()
A::~A()
A::~A()
A::~A()


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