On Tue, Apr 23, 2013 at 10:45 AM, Andrew Ho
Daniel Frey
writes: I don't quite understand what you have in mind, could you elaborate, please? For df.operators, you already have the choice of using commutative_foo
which provides both T foo U and U foo T (as it is commutative) and for the non-commutative version, you still have foo< T, U > for T foo U and foo_left< T, U > for U foo T. In general, I see two major options to improve Boost.Operators:
1) Small steps to improve the existing implementation, be as compatible as possible, be very conservative about changes. That might also mean to end up with a compromise and not with the best API and implementation for the conforming and good compilers and the people using them.
2) Leave Boost.Operators as it is and develop Boost.Operators v2 (using df.operators as a base?). This should allow for breaking the API for the better and to have a much cleaner implementation. Old compilers that need strange work-arounds can still use Boost.Operators v1 and they are unlikely to benefit from rvalue-reference support anyways.
I think that 2) might be the better option, giving us more freedom, reduce the complexity of discussions, decisions and the implementation while not breaking any existing code: Users need to explicitly decide to switch to v2, otherwise all existing code remains untouched. Everyone, please give me your preferences for either 1) or 2), thanks!
Offhand and without thinking about it too much, I like 2.
Ahh, true. left is only relevant for non-commutative.
What about using partial template specialization for handling commutative/non-commutative versions? This should make implementing 1) much easier, and I think is a slightly more elegant/flexible solution.
Here's some sample code:
// non-commutative template
Ideally this goes without saying, but at the very least this template parameter should be an enum, rather than a bool.
struct addable1 { friend T operator +( const T& lhs, const T& rhs ) { return std::move(T(lhs) += rhs); } friend T&& operator +( T&& lhs, const T& rhs ) { return std::move(lhs += rhs); } friend T&& operator +( T&& lhs, T&& rhs ) { return std::move(lhs += std::move(rhs)); } };
// commutative template <class T> struct addable1
{ friend T operator +( const T& lhs, const T& rhs ) { return std::move(T(lhs) += rhs); } friend T&& operator +( T&& lhs, const T& rhs ) { return std::move(lhs += rhs); } friend T&& operator +( T&& lhs, T&& rhs ) { return std::move(lhs += std::move(rhs)); } friend T&& operator +( const T& lhs, T&& rhs ) { return std::move(rhs += lhs); } };
- Jeff