Chris@16: // Boost operators.hpp header file ----------------------------------------// Chris@16: Chris@16: // (C) Copyright David Abrahams, Jeremy Siek, Daryle Walker 1999-2001. Chris@16: // Distributed under the Boost Software License, Version 1.0. (See Chris@16: // accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: // See http://www.boost.org/libs/utility/operators.htm for documentation. Chris@16: Chris@16: // Revision History Chris@16: // 16 Dec 10 Limit warning suppression for 4284 to older versions of VC++ Chris@16: // (Matthew Bradbury, fixes #4432) Chris@16: // 07 Aug 08 Added "euclidean" spelling. (Daniel Frey) Chris@16: // 03 Apr 08 Make sure "convertible to bool" is sufficient Chris@16: // for T::operator<, etc. (Daniel Frey) Chris@16: // 24 May 07 Changed empty_base to depend on T, see Chris@16: // http://svn.boost.org/trac/boost/ticket/979 Chris@16: // 21 Oct 02 Modified implementation of operators to allow compilers with a Chris@16: // correct named return value optimization (NRVO) to produce optimal Chris@16: // code. (Daniel Frey) Chris@16: // 02 Dec 01 Bug fixed in random_access_iteratable. (Helmut Zeisel) Chris@16: // 28 Sep 01 Factored out iterator operator groups. (Daryle Walker) Chris@16: // 27 Aug 01 'left' form for non commutative operators added; Chris@16: // additional classes for groups of related operators added; Chris@16: // workaround for empty base class optimization Chris@16: // bug of GCC 3.0 (Helmut Zeisel) Chris@16: // 25 Jun 01 output_iterator_helper changes: removed default template Chris@16: // parameters, added support for self-proxying, additional Chris@16: // documentation and tests (Aleksey Gurtovoy) Chris@16: // 29 May 01 Added operator classes for << and >>. Added input and output Chris@16: // iterator helper classes. Added classes to connect equality and Chris@16: // relational operators. Added classes for groups of related Chris@16: // operators. Reimplemented example operator and iterator helper Chris@16: // classes in terms of the new groups. (Daryle Walker, with help Chris@16: // from Alexy Gurtovoy) Chris@16: // 11 Feb 01 Fixed bugs in the iterator helpers which prevented explicitly Chris@16: // supplied arguments from actually being used (Dave Abrahams) Chris@16: // 04 Jul 00 Fixed NO_OPERATORS_IN_NAMESPACE bugs, major cleanup and Chris@16: // refactoring of compiler workarounds, additional documentation Chris@16: // (Alexy Gurtovoy and Mark Rodgers with some help and prompting from Chris@16: // Dave Abrahams) Chris@16: // 28 Jun 00 General cleanup and integration of bugfixes from Mark Rodgers and Chris@16: // Jeremy Siek (Dave Abrahams) Chris@16: // 20 Jun 00 Changes to accommodate Borland C++Builder 4 and Borland C++ 5.5 Chris@16: // (Mark Rodgers) Chris@16: // 20 Jun 00 Minor fixes to the prior revision (Aleksey Gurtovoy) Chris@16: // 10 Jun 00 Support for the base class chaining technique was added Chris@16: // (Aleksey Gurtovoy). See documentation and the comments below Chris@16: // for the details. Chris@16: // 12 Dec 99 Initial version with iterator operators (Jeremy Siek) Chris@16: // 18 Nov 99 Change name "divideable" to "dividable", remove unnecessary Chris@16: // specializations of dividable, subtractable, modable (Ed Brey) Chris@16: // 17 Nov 99 Add comments (Beman Dawes) Chris@16: // Remove unnecessary specialization of operators<> (Ed Brey) Chris@16: // 15 Nov 99 Fix less_than_comparable second operand type for first two Chris@16: // operators.(Beman Dawes) Chris@16: // 12 Nov 99 Add operators templates (Ed Brey) Chris@16: // 11 Nov 99 Add single template parameter version for compilers without Chris@16: // partial specialization (Beman Dawes) Chris@16: // 10 Nov 99 Initial version Chris@16: Chris@16: // 10 Jun 00: Chris@16: // An additional optional template parameter was added to most of Chris@16: // operator templates to support the base class chaining technique (see Chris@16: // documentation for the details). Unfortunately, a straightforward Chris@16: // implementation of this change would have broken compatibility with the Chris@16: // previous version of the library by making it impossible to use the same Chris@16: // template name (e.g. 'addable') for both the 1- and 2-argument versions of Chris@16: // an operator template. This implementation solves the backward-compatibility Chris@16: // issue at the cost of some simplicity. Chris@16: // Chris@16: // One of the complications is an existence of special auxiliary class template Chris@16: // 'is_chained_base<>' (see 'detail' namespace below), which is used Chris@16: // to determine whether its template parameter is a library's operator template Chris@16: // or not. You have to specialize 'is_chained_base<>' for each new Chris@16: // operator template you add to the library. Chris@16: // Chris@16: // However, most of the non-trivial implementation details are hidden behind Chris@16: // several local macros defined below, and as soon as you understand them, Chris@16: // you understand the whole library implementation. Chris@16: Chris@16: #ifndef BOOST_OPERATORS_HPP Chris@16: #define BOOST_OPERATORS_HPP Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #if defined(__sgi) && !defined(__GNUC__) Chris@16: # pragma set woff 1234 Chris@16: #endif Chris@16: Chris@16: #if BOOST_WORKAROUND(BOOST_MSVC, < 1600) Chris@16: # pragma warning( disable : 4284 ) // complaint about return type of Chris@16: #endif // operator-> not begin a UDT Chris@16: Chris@16: namespace boost { Chris@16: namespace detail { Chris@16: Chris@101: template class empty_base {}; Chris@16: Chris@16: } // namespace detail Chris@16: } // namespace boost Chris@16: Chris@16: // In this section we supply the xxxx1 and xxxx2 forms of the operator Chris@16: // templates, which are explicitly targeted at the 1-type-argument and Chris@16: // 2-type-argument operator forms, respectively. Some compilers get confused Chris@16: // when inline friend functions are overloaded in namespaces other than the Chris@16: // global namespace. When BOOST_NO_OPERATORS_IN_NAMESPACE is defined, all of Chris@16: // these templates must go in the global namespace. Chris@16: Chris@16: #ifndef BOOST_NO_OPERATORS_IN_NAMESPACE Chris@16: namespace boost Chris@16: { Chris@16: #endif Chris@16: Chris@16: // Basic operator classes (contributed by Dave Abrahams) ------------------// Chris@16: Chris@16: // Note that friend functions defined in a class are implicitly inline. Chris@16: // See the C++ std, 11.4 [class.friend] paragraph 5 Chris@16: Chris@16: template > Chris@16: struct less_than_comparable2 : B Chris@16: { Chris@16: friend bool operator<=(const T& x, const U& y) { return !static_cast(x > y); } Chris@16: friend bool operator>=(const T& x, const U& y) { return !static_cast(x < y); } Chris@16: friend bool operator>(const U& x, const T& y) { return y < x; } Chris@16: friend bool operator<(const U& x, const T& y) { return y > x; } Chris@16: friend bool operator<=(const U& x, const T& y) { return !static_cast(y < x); } Chris@16: friend bool operator>=(const U& x, const T& y) { return !static_cast(y > x); } Chris@16: }; Chris@16: Chris@16: template > Chris@16: struct less_than_comparable1 : B Chris@16: { Chris@16: friend bool operator>(const T& x, const T& y) { return y < x; } Chris@16: friend bool operator<=(const T& x, const T& y) { return !static_cast(y < x); } Chris@16: friend bool operator>=(const T& x, const T& y) { return !static_cast(x < y); } Chris@16: }; Chris@16: Chris@16: template > Chris@16: struct equality_comparable2 : B Chris@16: { Chris@16: friend bool operator==(const U& y, const T& x) { return x == y; } Chris@16: friend bool operator!=(const U& y, const T& x) { return !static_cast(x == y); } Chris@16: friend bool operator!=(const T& y, const U& x) { return !static_cast(y == x); } Chris@16: }; Chris@16: Chris@16: template > Chris@16: struct equality_comparable1 : B Chris@16: { Chris@16: friend bool operator!=(const T& x, const T& y) { return !static_cast(x == y); } Chris@16: }; Chris@16: Chris@16: // A macro which produces "name_2left" from "name". Chris@16: #define BOOST_OPERATOR2_LEFT(name) name##2##_##left Chris@16: Chris@16: // NRVO-friendly implementation (contributed by Daniel Frey) ---------------// Chris@16: Chris@16: #if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) Chris@16: Chris@16: // This is the optimal implementation for ISO/ANSI C++, Chris@16: // but it requires the compiler to implement the NRVO. Chris@16: // If the compiler has no NRVO, this is the best symmetric Chris@16: // implementation available. Chris@16: Chris@16: #define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \ Chris@16: template > \ Chris@16: struct NAME##2 : B \ Chris@16: { \ Chris@16: friend T operator OP( const T& lhs, const U& rhs ) \ Chris@16: { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ Chris@16: friend T operator OP( const U& lhs, const T& rhs ) \ Chris@16: { T nrv( rhs ); nrv OP##= lhs; return nrv; } \ Chris@16: }; \ Chris@16: \ Chris@16: template > \ Chris@16: struct NAME##1 : B \ Chris@16: { \ Chris@16: friend T operator OP( const T& lhs, const T& rhs ) \ Chris@16: { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ Chris@16: }; Chris@16: Chris@16: #define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \ Chris@16: template > \ Chris@16: struct NAME##2 : B \ Chris@16: { \ Chris@16: friend T operator OP( const T& lhs, const U& rhs ) \ Chris@16: { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ Chris@16: }; \ Chris@16: \ Chris@16: template > \ Chris@16: struct BOOST_OPERATOR2_LEFT(NAME) : B \ Chris@16: { \ Chris@16: friend T operator OP( const U& lhs, const T& rhs ) \ Chris@16: { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ Chris@16: }; \ Chris@16: \ Chris@16: template > \ Chris@16: struct NAME##1 : B \ Chris@16: { \ Chris@16: friend T operator OP( const T& lhs, const T& rhs ) \ Chris@16: { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ Chris@16: }; Chris@16: Chris@16: #else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) Chris@16: Chris@16: // For compilers without NRVO the following code is optimal, but not Chris@16: // symmetric! Note that the implementation of Chris@16: // BOOST_OPERATOR2_LEFT(NAME) only looks cool, but doesn't provide Chris@16: // optimization opportunities to the compiler :) Chris@16: Chris@16: #define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \ Chris@16: template > \ Chris@16: struct NAME##2 : B \ Chris@16: { \ Chris@16: friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \ Chris@16: friend T operator OP( const U& lhs, T rhs ) { return rhs OP##= lhs; } \ Chris@16: }; \ Chris@16: \ Chris@16: template > \ Chris@16: struct NAME##1 : B \ Chris@16: { \ Chris@16: friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \ Chris@16: }; Chris@16: Chris@16: #define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \ Chris@16: template > \ Chris@16: struct NAME##2 : B \ Chris@16: { \ Chris@16: friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \ Chris@16: }; \ Chris@16: \ Chris@16: template > \ Chris@16: struct BOOST_OPERATOR2_LEFT(NAME) : B \ Chris@16: { \ Chris@16: friend T operator OP( const U& lhs, const T& rhs ) \ Chris@16: { return T( lhs ) OP##= rhs; } \ Chris@16: }; \ Chris@16: \ Chris@16: template > \ Chris@16: struct NAME##1 : B \ Chris@16: { \ Chris@16: friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \ Chris@16: }; Chris@16: Chris@16: #endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) Chris@16: Chris@16: BOOST_BINARY_OPERATOR_COMMUTATIVE( multipliable, * ) Chris@16: BOOST_BINARY_OPERATOR_COMMUTATIVE( addable, + ) Chris@16: BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( subtractable, - ) Chris@16: BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( dividable, / ) Chris@16: BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( modable, % ) Chris@16: BOOST_BINARY_OPERATOR_COMMUTATIVE( xorable, ^ ) Chris@16: BOOST_BINARY_OPERATOR_COMMUTATIVE( andable, & ) Chris@16: BOOST_BINARY_OPERATOR_COMMUTATIVE( orable, | ) Chris@16: Chris@16: #undef BOOST_BINARY_OPERATOR_COMMUTATIVE Chris@16: #undef BOOST_BINARY_OPERATOR_NON_COMMUTATIVE Chris@16: #undef BOOST_OPERATOR2_LEFT Chris@16: Chris@16: // incrementable and decrementable contributed by Jeremy Siek Chris@16: Chris@16: template > Chris@16: struct incrementable : B Chris@16: { Chris@16: friend T operator++(T& x, int) Chris@16: { Chris@16: incrementable_type nrv(x); Chris@16: ++x; Chris@16: return nrv; Chris@16: } Chris@16: private: // The use of this typedef works around a Borland bug Chris@16: typedef T incrementable_type; Chris@16: }; Chris@16: Chris@16: template > Chris@16: struct decrementable : B Chris@16: { Chris@16: friend T operator--(T& x, int) Chris@16: { Chris@16: decrementable_type nrv(x); Chris@16: --x; Chris@16: return nrv; Chris@16: } Chris@16: private: // The use of this typedef works around a Borland bug Chris@16: typedef T decrementable_type; Chris@16: }; Chris@16: Chris@16: // Iterator operator classes (contributed by Jeremy Siek) ------------------// Chris@16: Chris@16: template > Chris@16: struct dereferenceable : B Chris@16: { Chris@16: P operator->() const Chris@16: { Chris@16: return &*static_cast(*this); Chris@16: } Chris@16: }; Chris@16: Chris@16: template > Chris@16: struct indexable : B Chris@16: { Chris@16: R operator[](I n) const Chris@16: { Chris@16: return *(static_cast(*this) + n); Chris@16: } Chris@16: }; Chris@16: Chris@16: // More operator classes (contributed by Daryle Walker) --------------------// Chris@16: // (NRVO-friendly implementation contributed by Daniel Frey) ---------------// Chris@16: Chris@16: #if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) Chris@16: Chris@16: #define BOOST_BINARY_OPERATOR( NAME, OP ) \ Chris@16: template > \ Chris@16: struct NAME##2 : B \ Chris@16: { \ Chris@16: friend T operator OP( const T& lhs, const U& rhs ) \ Chris@16: { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ Chris@16: }; \ Chris@16: \ Chris@16: template > \ Chris@16: struct NAME##1 : B \ Chris@16: { \ Chris@16: friend T operator OP( const T& lhs, const T& rhs ) \ Chris@16: { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ Chris@16: }; Chris@16: Chris@16: #else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) Chris@16: Chris@16: #define BOOST_BINARY_OPERATOR( NAME, OP ) \ Chris@16: template > \ Chris@16: struct NAME##2 : B \ Chris@16: { \ Chris@16: friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \ Chris@16: }; \ Chris@16: \ Chris@16: template > \ Chris@16: struct NAME##1 : B \ Chris@16: { \ Chris@16: friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \ Chris@16: }; Chris@16: Chris@16: #endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) Chris@16: Chris@16: BOOST_BINARY_OPERATOR( left_shiftable, << ) Chris@16: BOOST_BINARY_OPERATOR( right_shiftable, >> ) Chris@16: Chris@16: #undef BOOST_BINARY_OPERATOR Chris@16: Chris@16: template > Chris@16: struct equivalent2 : B Chris@16: { Chris@16: friend bool operator==(const T& x, const U& y) Chris@16: { Chris@16: return !static_cast(x < y) && !static_cast(x > y); Chris@16: } Chris@16: }; Chris@16: Chris@16: template > Chris@16: struct equivalent1 : B Chris@16: { Chris@16: friend bool operator==(const T&x, const T&y) Chris@16: { Chris@16: return !static_cast(x < y) && !static_cast(y < x); Chris@16: } Chris@16: }; Chris@16: Chris@16: template > Chris@16: struct partially_ordered2 : B Chris@16: { Chris@16: friend bool operator<=(const T& x, const U& y) Chris@16: { return static_cast(x < y) || static_cast(x == y); } Chris@16: friend bool operator>=(const T& x, const U& y) Chris@16: { return static_cast(x > y) || static_cast(x == y); } Chris@16: friend bool operator>(const U& x, const T& y) Chris@16: { return y < x; } Chris@16: friend bool operator<(const U& x, const T& y) Chris@16: { return y > x; } Chris@16: friend bool operator<=(const U& x, const T& y) Chris@16: { return static_cast(y > x) || static_cast(y == x); } Chris@16: friend bool operator>=(const U& x, const T& y) Chris@16: { return static_cast(y < x) || static_cast(y == x); } Chris@16: }; Chris@16: Chris@16: template > Chris@16: struct partially_ordered1 : B Chris@16: { Chris@16: friend bool operator>(const T& x, const T& y) Chris@16: { return y < x; } Chris@16: friend bool operator<=(const T& x, const T& y) Chris@16: { return static_cast(x < y) || static_cast(x == y); } Chris@16: friend bool operator>=(const T& x, const T& y) Chris@16: { return static_cast(y < x) || static_cast(x == y); } Chris@16: }; Chris@16: Chris@16: // Combined operator classes (contributed by Daryle Walker) ----------------// Chris@16: Chris@16: template > Chris@16: struct totally_ordered2 Chris@16: : less_than_comparable2 > {}; Chris@16: Chris@16: template > Chris@16: struct totally_ordered1 Chris@16: : less_than_comparable1 > {}; Chris@16: Chris@16: template > Chris@16: struct additive2 Chris@16: : addable2 > {}; Chris@16: Chris@16: template > Chris@16: struct additive1 Chris@16: : addable1 > {}; Chris@16: Chris@16: template > Chris@16: struct multiplicative2 Chris@16: : multipliable2 > {}; Chris@16: Chris@16: template > Chris@16: struct multiplicative1 Chris@16: : multipliable1 > {}; Chris@16: Chris@16: template > Chris@16: struct integer_multiplicative2 Chris@16: : multiplicative2 > {}; Chris@16: Chris@16: template > Chris@16: struct integer_multiplicative1 Chris@16: : multiplicative1 > {}; Chris@16: Chris@16: template > Chris@16: struct arithmetic2 Chris@16: : additive2 > {}; Chris@16: Chris@16: template > Chris@16: struct arithmetic1 Chris@16: : additive1 > {}; Chris@16: Chris@16: template > Chris@16: struct integer_arithmetic2 Chris@16: : additive2 > {}; Chris@16: Chris@16: template > Chris@16: struct integer_arithmetic1 Chris@16: : additive1 > {}; Chris@16: Chris@16: template > Chris@16: struct bitwise2 Chris@16: : xorable2 > > {}; Chris@16: Chris@16: template > Chris@16: struct bitwise1 Chris@16: : xorable1 > > {}; Chris@16: Chris@16: template > Chris@16: struct unit_steppable Chris@16: : incrementable > {}; Chris@16: Chris@16: template > Chris@16: struct shiftable2 Chris@16: : left_shiftable2 > {}; Chris@16: Chris@16: template > Chris@16: struct shiftable1 Chris@16: : left_shiftable1 > {}; Chris@16: Chris@16: template > Chris@16: struct ring_operators2 Chris@16: : additive2 > > {}; Chris@16: Chris@16: template > Chris@16: struct ring_operators1 Chris@16: : additive1 > {}; Chris@16: Chris@16: template > Chris@16: struct ordered_ring_operators2 Chris@16: : ring_operators2 > {}; Chris@16: Chris@16: template > Chris@16: struct ordered_ring_operators1 Chris@16: : ring_operators1 > {}; Chris@16: Chris@16: template > Chris@16: struct field_operators2 Chris@16: : ring_operators2 > > {}; Chris@16: Chris@16: template > Chris@16: struct field_operators1 Chris@16: : ring_operators1 > {}; Chris@16: Chris@16: template > Chris@16: struct ordered_field_operators2 Chris@16: : field_operators2 > {}; Chris@16: Chris@16: template > Chris@16: struct ordered_field_operators1 Chris@16: : field_operators1 > {}; Chris@16: Chris@16: template > Chris@16: struct euclidian_ring_operators2 Chris@16: : ring_operators2 > > > > {}; Chris@16: Chris@16: template > Chris@16: struct euclidian_ring_operators1 Chris@16: : ring_operators1 > > {}; Chris@16: Chris@16: template > Chris@16: struct ordered_euclidian_ring_operators2 Chris@16: : totally_ordered2 > {}; Chris@16: Chris@16: template > Chris@16: struct ordered_euclidian_ring_operators1 Chris@16: : totally_ordered1 > {}; Chris@16: Chris@16: template > Chris@16: struct euclidean_ring_operators2 Chris@16: : ring_operators2 > > > > {}; Chris@16: Chris@16: template > Chris@16: struct euclidean_ring_operators1 Chris@16: : ring_operators1 > > {}; Chris@16: Chris@16: template > Chris@16: struct ordered_euclidean_ring_operators2 Chris@16: : totally_ordered2 > {}; Chris@16: Chris@16: template > Chris@16: struct ordered_euclidean_ring_operators1 Chris@16: : totally_ordered1 > {}; Chris@16: Chris@16: template > Chris@16: struct input_iteratable Chris@16: : equality_comparable1 > > {}; Chris@16: Chris@16: template > Chris@16: struct output_iteratable Chris@16: : incrementable {}; Chris@16: Chris@16: template > Chris@16: struct forward_iteratable Chris@16: : input_iteratable {}; Chris@16: Chris@16: template > Chris@16: struct bidirectional_iteratable Chris@16: : forward_iteratable > {}; Chris@16: Chris@16: // To avoid repeated derivation from equality_comparable, Chris@16: // which is an indirect base class of bidirectional_iterable, Chris@16: // random_access_iteratable must not be derived from totally_ordered1 Chris@16: // but from less_than_comparable1 only. (Helmut Zeisel, 02-Dec-2001) Chris@16: template > Chris@16: struct random_access_iteratable Chris@16: : bidirectional_iteratable > > > {}; Chris@16: Chris@16: #ifndef BOOST_NO_OPERATORS_IN_NAMESPACE Chris@16: } // namespace boost Chris@16: #endif // BOOST_NO_OPERATORS_IN_NAMESPACE Chris@16: Chris@16: Chris@16: // BOOST_IMPORT_TEMPLATE1 .. BOOST_IMPORT_TEMPLATE4 - Chris@16: // Chris@16: // When BOOST_NO_OPERATORS_IN_NAMESPACE is defined we need a way to import an Chris@16: // operator template into the boost namespace. BOOST_IMPORT_TEMPLATE1 is used Chris@16: // for one-argument forms of operator templates; BOOST_IMPORT_TEMPLATE2 for Chris@16: // two-argument forms. Note that these macros expect to be invoked from within Chris@16: // boost. Chris@16: Chris@16: #ifndef BOOST_NO_OPERATORS_IN_NAMESPACE Chris@16: Chris@16: // The template is already in boost so we have nothing to do. Chris@16: # define BOOST_IMPORT_TEMPLATE4(template_name) Chris@16: # define BOOST_IMPORT_TEMPLATE3(template_name) Chris@16: # define BOOST_IMPORT_TEMPLATE2(template_name) Chris@16: # define BOOST_IMPORT_TEMPLATE1(template_name) Chris@16: Chris@16: #else // BOOST_NO_OPERATORS_IN_NAMESPACE Chris@16: Chris@16: # ifndef BOOST_NO_USING_TEMPLATE Chris@16: Chris@16: // Bring the names in with a using-declaration Chris@16: // to avoid stressing the compiler. Chris@16: # define BOOST_IMPORT_TEMPLATE4(template_name) using ::template_name; Chris@16: # define BOOST_IMPORT_TEMPLATE3(template_name) using ::template_name; Chris@16: # define BOOST_IMPORT_TEMPLATE2(template_name) using ::template_name; Chris@16: # define BOOST_IMPORT_TEMPLATE1(template_name) using ::template_name; Chris@16: Chris@16: # else Chris@16: Chris@16: // Otherwise, because a Borland C++ 5.5 bug prevents a using declaration Chris@16: // from working, we are forced to use inheritance for that compiler. Chris@16: # define BOOST_IMPORT_TEMPLATE4(template_name) \ Chris@16: template > \ Chris@16: struct template_name : ::template_name {}; Chris@16: Chris@16: # define BOOST_IMPORT_TEMPLATE3(template_name) \ Chris@16: template > \ Chris@16: struct template_name : ::template_name {}; Chris@16: Chris@16: # define BOOST_IMPORT_TEMPLATE2(template_name) \ Chris@16: template > \ Chris@16: struct template_name : ::template_name {}; Chris@16: Chris@16: # define BOOST_IMPORT_TEMPLATE1(template_name) \ Chris@16: template > \ Chris@16: struct template_name : ::template_name {}; Chris@16: Chris@16: # endif // BOOST_NO_USING_TEMPLATE Chris@16: Chris@16: #endif // BOOST_NO_OPERATORS_IN_NAMESPACE Chris@16: Chris@16: // Chris@16: // Here's where we put it all together, defining the xxxx forms of the templates Chris@16: // in namespace boost. We also define specializations of is_chained_base<> for Chris@16: // the xxxx, xxxx1, and xxxx2 templates, importing them into boost:: as Chris@16: // necessary. Chris@16: // Chris@16: Chris@16: // is_chained_base<> - a traits class used to distinguish whether an operator Chris@16: // template argument is being used for base class chaining, or is specifying a Chris@16: // 2nd argument type. Chris@16: Chris@16: namespace boost { Chris@16: // A type parameter is used instead of a plain bool because Borland's compiler Chris@16: // didn't cope well with the more obvious non-type template parameter. Chris@16: namespace detail { Chris@16: struct true_t {}; Chris@16: struct false_t {}; Chris@16: } // namespace detail Chris@16: Chris@16: // Unspecialized version assumes that most types are not being used for base Chris@16: // class chaining. We specialize for the operator templates defined in this Chris@16: // library. Chris@16: template struct is_chained_base { Chris@16: typedef ::boost::detail::false_t value; Chris@16: }; Chris@16: Chris@16: } // namespace boost Chris@16: Chris@16: // Import a 4-type-argument operator template into boost (if necessary) and Chris@16: // provide a specialization of 'is_chained_base<>' for it. Chris@16: # define BOOST_OPERATOR_TEMPLATE4(template_name4) \ Chris@16: BOOST_IMPORT_TEMPLATE4(template_name4) \ Chris@16: template \ Chris@16: struct is_chained_base< ::boost::template_name4 > { \ Chris@16: typedef ::boost::detail::true_t value; \ Chris@16: }; Chris@16: Chris@16: // Import a 3-type-argument operator template into boost (if necessary) and Chris@16: // provide a specialization of 'is_chained_base<>' for it. Chris@16: # define BOOST_OPERATOR_TEMPLATE3(template_name3) \ Chris@16: BOOST_IMPORT_TEMPLATE3(template_name3) \ Chris@16: template \ Chris@16: struct is_chained_base< ::boost::template_name3 > { \ Chris@16: typedef ::boost::detail::true_t value; \ Chris@16: }; Chris@16: Chris@16: // Import a 2-type-argument operator template into boost (if necessary) and Chris@16: // provide a specialization of 'is_chained_base<>' for it. Chris@16: # define BOOST_OPERATOR_TEMPLATE2(template_name2) \ Chris@16: BOOST_IMPORT_TEMPLATE2(template_name2) \ Chris@16: template \ Chris@16: struct is_chained_base< ::boost::template_name2 > { \ Chris@16: typedef ::boost::detail::true_t value; \ Chris@16: }; Chris@16: Chris@16: // Import a 1-type-argument operator template into boost (if necessary) and Chris@16: // provide a specialization of 'is_chained_base<>' for it. Chris@16: # define BOOST_OPERATOR_TEMPLATE1(template_name1) \ Chris@16: BOOST_IMPORT_TEMPLATE1(template_name1) \ Chris@16: template \ Chris@16: struct is_chained_base< ::boost::template_name1 > { \ Chris@16: typedef ::boost::detail::true_t value; \ Chris@16: }; Chris@16: Chris@16: // BOOST_OPERATOR_TEMPLATE(template_name) defines template_name<> such that it Chris@16: // can be used for specifying both 1-argument and 2-argument forms. Requires the Chris@16: // existence of two previously defined class templates named '1' Chris@16: // and '2' which must implement the corresponding 1- and 2- Chris@16: // argument forms. Chris@16: // Chris@16: // The template type parameter O == is_chained_base::value is used to Chris@16: // distinguish whether the 2nd argument to is being used for Chris@16: // base class chaining from another boost operator template or is describing a Chris@16: // 2nd operand type. O == true_t only when U is actually an another operator Chris@16: // template from the library. Partial specialization is used to select an Chris@16: // implementation in terms of either '1' or '2'. Chris@16: // Chris@16: Chris@16: # define BOOST_OPERATOR_TEMPLATE(template_name) \ Chris@16: template \ Chris@16: ,class O = typename is_chained_base::value \ Chris@16: > \ Chris@16: struct template_name : template_name##2 {}; \ Chris@16: \ Chris@16: template \ Chris@16: struct template_name \ Chris@16: : template_name##1 {}; \ Chris@16: \ Chris@16: template \ Chris@16: struct template_name \ Chris@16: : template_name##1 {}; \ Chris@16: \ Chris@16: template \ Chris@16: struct is_chained_base< ::boost::template_name > { \ Chris@16: typedef ::boost::detail::true_t value; \ Chris@16: }; \ Chris@16: \ Chris@16: BOOST_OPERATOR_TEMPLATE2(template_name##2) \ Chris@16: BOOST_OPERATOR_TEMPLATE1(template_name##1) Chris@16: Chris@16: Chris@16: Chris@16: namespace boost { Chris@16: Chris@16: BOOST_OPERATOR_TEMPLATE(less_than_comparable) Chris@16: BOOST_OPERATOR_TEMPLATE(equality_comparable) Chris@16: BOOST_OPERATOR_TEMPLATE(multipliable) Chris@16: BOOST_OPERATOR_TEMPLATE(addable) Chris@16: BOOST_OPERATOR_TEMPLATE(subtractable) Chris@16: BOOST_OPERATOR_TEMPLATE2(subtractable2_left) Chris@16: BOOST_OPERATOR_TEMPLATE(dividable) Chris@16: BOOST_OPERATOR_TEMPLATE2(dividable2_left) Chris@16: BOOST_OPERATOR_TEMPLATE(modable) Chris@16: BOOST_OPERATOR_TEMPLATE2(modable2_left) Chris@16: BOOST_OPERATOR_TEMPLATE(xorable) Chris@16: BOOST_OPERATOR_TEMPLATE(andable) Chris@16: BOOST_OPERATOR_TEMPLATE(orable) Chris@16: Chris@16: BOOST_OPERATOR_TEMPLATE1(incrementable) Chris@16: BOOST_OPERATOR_TEMPLATE1(decrementable) Chris@16: Chris@16: BOOST_OPERATOR_TEMPLATE2(dereferenceable) Chris@16: BOOST_OPERATOR_TEMPLATE3(indexable) Chris@16: Chris@16: BOOST_OPERATOR_TEMPLATE(left_shiftable) Chris@16: BOOST_OPERATOR_TEMPLATE(right_shiftable) Chris@16: BOOST_OPERATOR_TEMPLATE(equivalent) Chris@16: BOOST_OPERATOR_TEMPLATE(partially_ordered) Chris@16: Chris@16: BOOST_OPERATOR_TEMPLATE(totally_ordered) Chris@16: BOOST_OPERATOR_TEMPLATE(additive) Chris@16: BOOST_OPERATOR_TEMPLATE(multiplicative) Chris@16: BOOST_OPERATOR_TEMPLATE(integer_multiplicative) Chris@16: BOOST_OPERATOR_TEMPLATE(arithmetic) Chris@16: BOOST_OPERATOR_TEMPLATE(integer_arithmetic) Chris@16: BOOST_OPERATOR_TEMPLATE(bitwise) Chris@16: BOOST_OPERATOR_TEMPLATE1(unit_steppable) Chris@16: BOOST_OPERATOR_TEMPLATE(shiftable) Chris@16: BOOST_OPERATOR_TEMPLATE(ring_operators) Chris@16: BOOST_OPERATOR_TEMPLATE(ordered_ring_operators) Chris@16: BOOST_OPERATOR_TEMPLATE(field_operators) Chris@16: BOOST_OPERATOR_TEMPLATE(ordered_field_operators) Chris@16: BOOST_OPERATOR_TEMPLATE(euclidian_ring_operators) Chris@16: BOOST_OPERATOR_TEMPLATE(ordered_euclidian_ring_operators) Chris@16: BOOST_OPERATOR_TEMPLATE(euclidean_ring_operators) Chris@16: BOOST_OPERATOR_TEMPLATE(ordered_euclidean_ring_operators) Chris@16: BOOST_OPERATOR_TEMPLATE2(input_iteratable) Chris@16: BOOST_OPERATOR_TEMPLATE1(output_iteratable) Chris@16: BOOST_OPERATOR_TEMPLATE2(forward_iteratable) Chris@16: BOOST_OPERATOR_TEMPLATE2(bidirectional_iteratable) Chris@16: BOOST_OPERATOR_TEMPLATE4(random_access_iteratable) Chris@16: Chris@16: #undef BOOST_OPERATOR_TEMPLATE Chris@16: #undef BOOST_OPERATOR_TEMPLATE4 Chris@16: #undef BOOST_OPERATOR_TEMPLATE3 Chris@16: #undef BOOST_OPERATOR_TEMPLATE2 Chris@16: #undef BOOST_OPERATOR_TEMPLATE1 Chris@16: #undef BOOST_IMPORT_TEMPLATE1 Chris@16: #undef BOOST_IMPORT_TEMPLATE2 Chris@16: #undef BOOST_IMPORT_TEMPLATE3 Chris@16: #undef BOOST_IMPORT_TEMPLATE4 Chris@16: Chris@16: // The following 'operators' classes can only be used portably if the derived class Chris@16: // declares ALL of the required member operators. Chris@16: template Chris@16: struct operators2 Chris@16: : totally_ordered2 > > {}; Chris@16: Chris@16: template Chris@16: struct operators : operators2 {}; Chris@16: Chris@16: template struct operators Chris@16: : totally_ordered > > > {}; Chris@16: Chris@16: // Iterator helper classes (contributed by Jeremy Siek) -------------------// Chris@16: // (Input and output iterator helpers contributed by Daryle Walker) -------// Chris@16: // (Changed to use combined operator classes by Daryle Walker) ------------// Chris@16: template Chris@16: struct input_iterator_helper Chris@16: : input_iteratable > {}; Chris@16: Chris@16: template Chris@16: struct output_iterator_helper Chris@16: : output_iteratable > Chris@16: { Chris@16: T& operator*() { return static_cast(*this); } Chris@16: T& operator++() { return static_cast(*this); } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct forward_iterator_helper Chris@16: : forward_iteratable > {}; Chris@16: Chris@16: template Chris@16: struct bidirectional_iterator_helper Chris@16: : bidirectional_iteratable > {}; Chris@16: Chris@16: template Chris@16: struct random_access_iterator_helper Chris@16: : random_access_iteratable > Chris@16: { Chris@16: friend D requires_difference_operator(const T& x, const T& y) { Chris@16: return x - y; Chris@16: } Chris@16: }; // random_access_iterator_helper Chris@16: Chris@16: } // namespace boost Chris@16: Chris@16: #if defined(__sgi) && !defined(__GNUC__) Chris@16: #pragma reset woff 1234 Chris@16: #endif Chris@16: Chris@16: #endif // BOOST_OPERATORS_HPP