-template <class T, class U, class B = ::boost::detail::empty_base>
-struct multipliable2 : B
-{
- friend T operator*(T x, const U& y) { return x *= y; }
- friend T operator*(const U& y, T x) { return x *= y; }
-};
-
-template <class T, class B = ::boost::detail::empty_base>
-struct multipliable1 : B
-{
- friend T operator*(T x, const T& y) { return x *= y; }
-};
-
-template <class T, class U, class B = ::boost::detail::empty_base>
-struct addable2 : B
-{
- friend T operator+(T x, const U& y) { return x += y; }
- friend T operator+(const U& y, T x) { return x += y; }
-};
-
-template <class T, class B = ::boost::detail::empty_base>
-struct addable1 : B
-{
- friend T operator+(T x, const T& y) { return x += y; }
-};
-
-template <class T, class U, class B = ::boost::detail::empty_base>
-struct subtractable2 : B
-{
- friend T operator-(T x, const U& y) { return x -= y; }
-};
-
-template <class T, class U, class B = ::boost::detail::empty_base>
-struct subtractable2_left : B
-{
- friend T operator-(const U& x, const T& y)
- { T result(x); return result -= y; }
-};
-
-template <class T, class B = ::boost::detail::empty_base>
-struct subtractable1 : B
-{
- friend T operator-(T x, const T& y) { return x -= y; }
-};
-
-template <class T, class U, class B = ::boost::detail::empty_base>
-struct dividable2 : B
-{
- friend T operator/(T x, const U& y) { return x /= y; }
-};
-
-template <class T, class U, class B = ::boost::detail::empty_base>
-struct dividable2_left : B
-{
- friend T operator/(const U& x, const T& y)
- { T result(x); return result /= y; }
-};
-
-template <class T, class B = ::boost::detail::empty_base>
-struct dividable1 : B
-{
- friend T operator/(T x, const T& y) { return x /= y; }
-};
-
-template <class T, class U, class B = ::boost::detail::empty_base>
-struct modable2 : B
-{
- friend T operator%(T x, const U& y) { return x %= y; }
-};
-
-template <class T, class U, class B = ::boost::detail::empty_base>
-struct modable2_left : B
-{
- friend T operator%(const U& x, const T& y)
- { T result(x); return result %= y; }
-};
-
-template <class T, class B = ::boost::detail::empty_base>
-struct modable1 : B
-{
- friend T operator%(T x, const T& y) { return x %= y; }
-};
-
-template <class T, class U, class B = ::boost::detail::empty_base>
-struct xorable2 : B
-{
- friend T operator^(T x, const U& y) { return x ^= y; }
- friend T operator^(const U& y, T x) { return x ^= y; }
-};
-
-template <class T, class B = ::boost::detail::empty_base>
-struct xorable1 : B
-{
- friend T operator^(T x, const T& y) { return x ^= y; }
-};
-
-template <class T, class U, class B = ::boost::detail::empty_base>
-struct andable2 : B
-{
- friend T operator&(T x, const U& y) { return x &= y; }
- friend T operator&(const U& y, T x) { return x &= y; }
-};
-
-template <class T, class B = ::boost::detail::empty_base>
-struct andable1 : B
-{
- friend T operator&(T x, const T& y) { return x &= y; }
-};
-
-template <class T, class U, class B = ::boost::detail::empty_base>
-struct orable2 : B
-{
- friend T operator|(T x, const U& y) { return x |= y; }
- friend T operator|(const U& y, T x) { return x |= y; }
-};
-
-template <class T, class B = ::boost::detail::empty_base>
-struct orable1 : B
-{
- friend T operator|(T x, const T& y) { return x |= y; }
-};
+// A macro which produces "name_2left" from "name".
+#define BOOST_OPERATOR2_LEFT(name) name##2##_##left
+
+// NRVO-friendly implementation (contributed by Daniel Frey) ---------------//
+
+#if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
+
+// This is the optimal implementation for ISO/ANSI C++,
+// but it requires the compiler to implement the NRVO.
+// If the compiler has no NRVO, this is the best symmetric
+// implementation available.
+
+#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
+template <class T, class U, class B = ::boost::detail::empty_base> \
+struct NAME##2 : B \
+{ \
+ friend T operator OP( const T& lhs, const U& rhs ) \
+ { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
+ friend T operator OP( const U& lhs, const T& rhs ) \
+ { T nrv( rhs ); nrv OP##= lhs; return nrv; } \
+}; \
+ \
+template <class T, class B = ::boost::detail::empty_base> \
+struct NAME##1 : B \
+{ \
+ friend T operator OP( const T& lhs, const T& rhs ) \
+ { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
+};
+
+#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \
+template <class T, class U, class B = ::boost::detail::empty_base> \
+struct NAME##2 : B \
+{ \
+ friend T operator OP( const T& lhs, const U& rhs ) \
+ { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
+}; \
+ \
+template <class T, class U, class B = ::boost::detail::empty_base> \
+struct BOOST_OPERATOR2_LEFT(NAME) : B \
+{ \
+ friend T operator OP( const U& lhs, const T& rhs ) \
+ { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
+}; \
+ \
+template <class T, class B = ::boost::detail::empty_base> \
+struct NAME##1 : B \
+{ \
+ friend T operator OP( const T& lhs, const T& rhs ) \
+ { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
+};
+
+#else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
+
+// For compilers without NRVO the following code is optimal, but not
+// symmetric! Note that the implementation of
+// BOOST_OPERATOR2_LEFT(NAME) only looks cool, but doesn't provide
+// optimization opportunities to the compiler :)
+
+#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
+template <class T, class U, class B = ::boost::detail::empty_base> \
+struct NAME##2 : B \
+{ \
+ friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
+ friend T operator OP( const U& lhs, T rhs ) { return rhs OP##= lhs; } \
+}; \
+ \
+template <class T, class B = ::boost::detail::empty_base> \
+struct NAME##1 : B \
+{ \
+ friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
+};
+
+#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \
+template <class T, class U, class B = ::boost::detail::empty_base> \
+struct NAME##2 : B \
+{ \
+ friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
+}; \
+ \
+template <class T, class U, class B = ::boost::detail::empty_base> \
+struct BOOST_OPERATOR2_LEFT(NAME) : B \
+{ \
+ friend T operator OP( const U& lhs, const T& rhs ) \
+ { return T( lhs ) OP##= rhs; } \
+}; \
+ \
+template <class T, class B = ::boost::detail::empty_base> \
+struct NAME##1 : B \
+{ \
+ friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
+};
+
+#endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
+
+BOOST_BINARY_OPERATOR_COMMUTATIVE( multipliable, * )
+BOOST_BINARY_OPERATOR_COMMUTATIVE( addable, + )
+BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( subtractable, - )
+BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( dividable, / )
+BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( modable, % )
+BOOST_BINARY_OPERATOR_COMMUTATIVE( xorable, ^ )
+BOOST_BINARY_OPERATOR_COMMUTATIVE( andable, & )
+BOOST_BINARY_OPERATOR_COMMUTATIVE( orable, | )
+
+#undef BOOST_BINARY_OPERATOR_COMMUTATIVE
+#undef BOOST_BINARY_OPERATOR_NON_COMMUTATIVE
+#undef BOOST_OPERATOR2_LEFT