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