// Boost operators.hpp header file ----------------------------------------//
-// (C) Copyright David Abrahams, Jeremy Siek, and Daryle Walker 1999-2001.
-// Permission to copy, use, modify, sell and distribute this software is
-// granted provided this copyright notice appears in all copies. This
-// software is provided "as is" without express or implied warranty, and
-// with no claim as to its suitability for any purpose.
+// (C) Copyright David Abrahams, Jeremy Siek, Daryle Walker 1999-2001.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
-// See http://www.boost.org for most recent version including documentation.
+// See http://www.boost.org/libs/utility/operators.htm for documentation.
// Revision History
+// 21 Oct 02 Modified implementation of operators to allow compilers with a
+// correct named return value optimization (NRVO) to produce optimal
+// code. (Daniel Frey)
// 02 Dec 01 Bug fixed in random_access_iteratable. (Helmut Zeisel)
// 28 Sep 01 Factored out iterator operator groups. (Daryle Walker)
// 27 Aug 01 'left' form for non commutative operators added;
#include <boost/config.hpp>
#include <boost/iterator.hpp>
+#include <boost/detail/workaround.hpp>
#if defined(__sgi) && !defined(__GNUC__)
-#pragma set woff 1234
+# pragma set woff 1234
#endif
#if defined(BOOST_MSVC)
friend bool operator!=(const T& x, const T& y) { return !(x == y); }
};
-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
// incrementable and decrementable contributed by Jeremy Siek
{
friend T operator++(T& x, int)
{
- incrementable_type tmp(x);
+ incrementable_type nrv(x);
++x;
- return tmp;
+ return nrv;
}
private: // The use of this typedef works around a Borland bug
typedef T incrementable_type;
{
friend T operator--(T& x, int)
{
- decrementable_type tmp(x);
+ decrementable_type nrv(x);
--x;
- return tmp;
+ return nrv;
}
private: // The use of this typedef works around a Borland bug
typedef T decrementable_type;
};
// More operator classes (contributed by Daryle Walker) --------------------//
+// (NRVO-friendly implementation contributed by Daniel Frey) ---------------//
-template <class T, class U, class B = ::boost::detail::empty_base>
-struct left_shiftable2 : B
-{
- friend T operator<<(T x, const U& y) { return x <<= y; }
-};
+#if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
-template <class T, class B = ::boost::detail::empty_base>
-struct left_shiftable1 : B
-{
- friend T operator<<(T x, const T& y) { return x <<= y; }
+#define BOOST_BINARY_OPERATOR( 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 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; } \
};
-template <class T, class U, class B = ::boost::detail::empty_base>
-struct right_shiftable2 : B
-{
- friend T operator>>(T x, const U& y) { return x >>= y; }
-};
+#else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
-template <class T, class B = ::boost::detail::empty_base>
-struct right_shiftable1 : B
-{
- friend T operator>>(T x, const T& y) { return x >>= y; }
+#define BOOST_BINARY_OPERATOR( 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 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( left_shiftable, << )
+BOOST_BINARY_OPERATOR( right_shiftable, >> )
+
+#undef BOOST_BINARY_OPERATOR
+
template <class T, class U, class B = ::boost::detail::empty_base>
struct equivalent2 : B
{
// Here's where we put it all together, defining the xxxx forms of the templates
// in namespace boost. We also define specializations of is_chained_base<> for
// the xxxx, xxxx1, and xxxx2 templates, importing them into boost:: as
-// neccessary.
+// necessary.
//
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
} // namespace boost
-// Import a 4-type-argument operator template into boost (if neccessary) and
+// Import a 4-type-argument operator template into boost (if necessary) and
// provide a specialization of 'is_chained_base<>' for it.
# define BOOST_OPERATOR_TEMPLATE4(template_name4) \
BOOST_IMPORT_TEMPLATE4(template_name4) \
typedef ::boost::detail::true_t value; \
};
-// Import a 3-type-argument operator template into boost (if neccessary) and
+// Import a 3-type-argument operator template into boost (if necessary) and
// provide a specialization of 'is_chained_base<>' for it.
# define BOOST_OPERATOR_TEMPLATE3(template_name3) \
BOOST_IMPORT_TEMPLATE3(template_name3) \
typedef ::boost::detail::true_t value; \
};
-// Import a 2-type-argument operator template into boost (if neccessary) and
+// Import a 2-type-argument operator template into boost (if necessary) and
// provide a specialization of 'is_chained_base<>' for it.
# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
BOOST_IMPORT_TEMPLATE2(template_name2) \
typedef ::boost::detail::true_t value; \
};
-// Import a 1-type-argument operator template into boost (if neccessary) and
+// Import a 1-type-argument operator template into boost (if necessary) and
// provide a specialization of 'is_chained_base<>' for it.
# define BOOST_OPERATOR_TEMPLATE1(template_name1) \
BOOST_IMPORT_TEMPLATE1(template_name1) \