1 // Boost operators.hpp header file ----------------------------------------//
3 // (C) Copyright David Abrahams, Jeremy Siek, Daryle Walker 1999-2001.
4 // (C) Copyright Daniel Frey 2002-2017.
5 // Distributed under the Boost Software License, Version 1.0. (See
6 // accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
9 // See http://www.boost.org/libs/utility/operators.htm for documentation.
12 // 23 Nov 17 Protect dereferenceable<> from overloaded operator&.
13 // 15 Oct 17 Adapted to C++17, replace std::iterator<> with manual
15 // 22 Feb 16 Added ADL protection, preserve old work-arounds in
16 // operators_v1.hpp and clean up this file. (Daniel Frey)
17 // 16 Dec 10 Limit warning suppression for 4284 to older versions of VC++
18 // (Matthew Bradbury, fixes #4432)
19 // 07 Aug 08 Added "euclidean" spelling. (Daniel Frey)
20 // 03 Apr 08 Make sure "convertible to bool" is sufficient
21 // for T::operator<, etc. (Daniel Frey)
22 // 24 May 07 Changed empty_base to depend on T, see
23 // http://svn.boost.org/trac/boost/ticket/979
24 // 21 Oct 02 Modified implementation of operators to allow compilers with a
25 // correct named return value optimization (NRVO) to produce optimal
26 // code. (Daniel Frey)
27 // 02 Dec 01 Bug fixed in random_access_iteratable. (Helmut Zeisel)
28 // 28 Sep 01 Factored out iterator operator groups. (Daryle Walker)
29 // 27 Aug 01 'left' form for non commutative operators added;
30 // additional classes for groups of related operators added;
31 // workaround for empty base class optimization
32 // bug of GCC 3.0 (Helmut Zeisel)
33 // 25 Jun 01 output_iterator_helper changes: removed default template
34 // parameters, added support for self-proxying, additional
35 // documentation and tests (Aleksey Gurtovoy)
36 // 29 May 01 Added operator classes for << and >>. Added input and output
37 // iterator helper classes. Added classes to connect equality and
38 // relational operators. Added classes for groups of related
39 // operators. Reimplemented example operator and iterator helper
40 // classes in terms of the new groups. (Daryle Walker, with help
41 // from Alexy Gurtovoy)
42 // 11 Feb 01 Fixed bugs in the iterator helpers which prevented explicitly
43 // supplied arguments from actually being used (Dave Abrahams)
44 // 04 Jul 00 Fixed NO_OPERATORS_IN_NAMESPACE bugs, major cleanup and
45 // refactoring of compiler workarounds, additional documentation
46 // (Alexy Gurtovoy and Mark Rodgers with some help and prompting from
48 // 28 Jun 00 General cleanup and integration of bugfixes from Mark Rodgers and
49 // Jeremy Siek (Dave Abrahams)
50 // 20 Jun 00 Changes to accommodate Borland C++Builder 4 and Borland C++ 5.5
52 // 20 Jun 00 Minor fixes to the prior revision (Aleksey Gurtovoy)
53 // 10 Jun 00 Support for the base class chaining technique was added
54 // (Aleksey Gurtovoy). See documentation and the comments below
56 // 12 Dec 99 Initial version with iterator operators (Jeremy Siek)
57 // 18 Nov 99 Change name "divideable" to "dividable", remove unnecessary
58 // specializations of dividable, subtractable, modable (Ed Brey)
59 // 17 Nov 99 Add comments (Beman Dawes)
60 // Remove unnecessary specialization of operators<> (Ed Brey)
61 // 15 Nov 99 Fix less_than_comparable<T,U> second operand type for first two
62 // operators.(Beman Dawes)
63 // 12 Nov 99 Add operators templates (Ed Brey)
64 // 11 Nov 99 Add single template parameter version for compilers without
65 // partial specialization (Beman Dawes)
66 // 10 Nov 99 Initial version
69 // An additional optional template parameter was added to most of
70 // operator templates to support the base class chaining technique (see
71 // documentation for the details). Unfortunately, a straightforward
72 // implementation of this change would have broken compatibility with the
73 // previous version of the library by making it impossible to use the same
74 // template name (e.g. 'addable') for both the 1- and 2-argument versions of
75 // an operator template. This implementation solves the backward-compatibility
76 // issue at the cost of some simplicity.
78 // One of the complications is an existence of special auxiliary class template
79 // 'is_chained_base<>' (see 'operators_detail' namespace below), which is used
80 // to determine whether its template parameter is a library's operator template
81 // or not. You have to specialize 'is_chained_base<>' for each new
82 // operator template you add to the library.
84 // However, most of the non-trivial implementation details are hidden behind
85 // several local macros defined below, and as soon as you understand them,
86 // you understand the whole library implementation.
88 #ifndef BOOST_OPERATORS_HPP
89 #define BOOST_OPERATORS_HPP
91 // If old work-arounds are needed, refer to the preserved version without
93 #if defined(BOOST_NO_OPERATORS_IN_NAMESPACE) || defined(BOOST_USE_OPERATORS_V1)
94 #include "operators_v1.hpp"
100 #include <boost/config.hpp>
101 #include <boost/detail/workaround.hpp>
102 #include <boost/core/addressof.hpp>
104 #if defined(__sgi) && !defined(__GNUC__)
105 # pragma set woff 1234
108 #if BOOST_WORKAROUND(BOOST_MSVC, < 1600)
109 # pragma warning( disable : 4284 ) // complaint about return type of
110 #endif // operator-> not begin a UDT
112 // In this section we supply the xxxx1 and xxxx2 forms of the operator
113 // templates, which are explicitly targeted at the 1-type-argument and
114 // 2-type-argument operator forms, respectively.
118 namespace operators_impl
120 namespace operators_detail
123 template <typename T> class empty_base {};
125 } // namespace operators_detail
127 // Basic operator classes (contributed by Dave Abrahams) ------------------//
129 // Note that friend functions defined in a class are implicitly inline.
130 // See the C++ std, 11.4 [class.friend] paragraph 5
132 template <class T, class U, class B = operators_detail::empty_base<T> >
133 struct less_than_comparable2 : B
135 friend bool operator<=(const T& x, const U& y) { return !static_cast<bool>(x > y); }
136 friend bool operator>=(const T& x, const U& y) { return !static_cast<bool>(x < y); }
137 friend bool operator>(const U& x, const T& y) { return y < x; }
138 friend bool operator<(const U& x, const T& y) { return y > x; }
139 friend bool operator<=(const U& x, const T& y) { return !static_cast<bool>(y < x); }
140 friend bool operator>=(const U& x, const T& y) { return !static_cast<bool>(y > x); }
143 template <class T, class B = operators_detail::empty_base<T> >
144 struct less_than_comparable1 : B
146 friend bool operator>(const T& x, const T& y) { return y < x; }
147 friend bool operator<=(const T& x, const T& y) { return !static_cast<bool>(y < x); }
148 friend bool operator>=(const T& x, const T& y) { return !static_cast<bool>(x < y); }
151 template <class T, class U, class B = operators_detail::empty_base<T> >
152 struct equality_comparable2 : B
154 friend bool operator==(const U& y, const T& x) { return x == y; }
155 friend bool operator!=(const U& y, const T& x) { return !static_cast<bool>(x == y); }
156 friend bool operator!=(const T& y, const U& x) { return !static_cast<bool>(y == x); }
159 template <class T, class B = operators_detail::empty_base<T> >
160 struct equality_comparable1 : B
162 friend bool operator!=(const T& x, const T& y) { return !static_cast<bool>(x == y); }
165 // A macro which produces "name_2left" from "name".
166 #define BOOST_OPERATOR2_LEFT(name) name##2##_##left
168 // NRVO-friendly implementation (contributed by Daniel Frey) ---------------//
170 #if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
172 // This is the optimal implementation for ISO/ANSI C++,
173 // but it requires the compiler to implement the NRVO.
174 // If the compiler has no NRVO, this is the best symmetric
175 // implementation available.
177 #define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
178 template <class T, class U, class B = operators_detail::empty_base<T> > \
181 friend T operator OP( const T& lhs, const U& rhs ) \
182 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
183 friend T operator OP( const U& lhs, const T& rhs ) \
184 { T nrv( rhs ); nrv OP##= lhs; return nrv; } \
187 template <class T, class B = operators_detail::empty_base<T> > \
190 friend T operator OP( const T& lhs, const T& rhs ) \
191 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
194 #define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \
195 template <class T, class U, class B = operators_detail::empty_base<T> > \
198 friend T operator OP( const T& lhs, const U& rhs ) \
199 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
202 template <class T, class U, class B = operators_detail::empty_base<T> > \
203 struct BOOST_OPERATOR2_LEFT(NAME) : B \
205 friend T operator OP( const U& lhs, const T& rhs ) \
206 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
209 template <class T, class B = operators_detail::empty_base<T> > \
212 friend T operator OP( const T& lhs, const T& rhs ) \
213 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
216 #else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
218 // For compilers without NRVO the following code is optimal, but not
219 // symmetric! Note that the implementation of
220 // BOOST_OPERATOR2_LEFT(NAME) only looks cool, but doesn't provide
221 // optimization opportunities to the compiler :)
223 #define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
224 template <class T, class U, class B = operators_detail::empty_base<T> > \
227 friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
228 friend T operator OP( const U& lhs, T rhs ) { return rhs OP##= lhs; } \
231 template <class T, class B = operators_detail::empty_base<T> > \
234 friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
237 #define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \
238 template <class T, class U, class B = operators_detail::empty_base<T> > \
241 friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
244 template <class T, class U, class B = operators_detail::empty_base<T> > \
245 struct BOOST_OPERATOR2_LEFT(NAME) : B \
247 friend T operator OP( const U& lhs, const T& rhs ) \
248 { return T( lhs ) OP##= rhs; } \
251 template <class T, class B = operators_detail::empty_base<T> > \
254 friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
257 #endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
259 BOOST_BINARY_OPERATOR_COMMUTATIVE( multipliable, * )
260 BOOST_BINARY_OPERATOR_COMMUTATIVE( addable, + )
261 BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( subtractable, - )
262 BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( dividable, / )
263 BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( modable, % )
264 BOOST_BINARY_OPERATOR_COMMUTATIVE( xorable, ^ )
265 BOOST_BINARY_OPERATOR_COMMUTATIVE( andable, & )
266 BOOST_BINARY_OPERATOR_COMMUTATIVE( orable, | )
268 #undef BOOST_BINARY_OPERATOR_COMMUTATIVE
269 #undef BOOST_BINARY_OPERATOR_NON_COMMUTATIVE
270 #undef BOOST_OPERATOR2_LEFT
272 // incrementable and decrementable contributed by Jeremy Siek
274 template <class T, class B = operators_detail::empty_base<T> >
275 struct incrementable : B
277 friend T operator++(T& x, int)
279 incrementable_type nrv(x);
283 private: // The use of this typedef works around a Borland bug
284 typedef T incrementable_type;
287 template <class T, class B = operators_detail::empty_base<T> >
288 struct decrementable : B
290 friend T operator--(T& x, int)
292 decrementable_type nrv(x);
296 private: // The use of this typedef works around a Borland bug
297 typedef T decrementable_type;
300 // Iterator operator classes (contributed by Jeremy Siek) ------------------//
302 template <class T, class P, class B = operators_detail::empty_base<T> >
303 struct dereferenceable : B
307 return ::boost::addressof(*static_cast<const T&>(*this));
311 template <class T, class I, class R, class B = operators_detail::empty_base<T> >
314 R operator[](I n) const
316 return *(static_cast<const T&>(*this) + n);
320 // More operator classes (contributed by Daryle Walker) --------------------//
321 // (NRVO-friendly implementation contributed by Daniel Frey) ---------------//
323 #if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
325 #define BOOST_BINARY_OPERATOR( NAME, OP ) \
326 template <class T, class U, class B = operators_detail::empty_base<T> > \
329 friend T operator OP( const T& lhs, const U& rhs ) \
330 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
333 template <class T, class B = operators_detail::empty_base<T> > \
336 friend T operator OP( const T& lhs, const T& rhs ) \
337 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
340 #else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
342 #define BOOST_BINARY_OPERATOR( NAME, OP ) \
343 template <class T, class U, class B = operators_detail::empty_base<T> > \
346 friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
349 template <class T, class B = operators_detail::empty_base<T> > \
352 friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
355 #endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
357 BOOST_BINARY_OPERATOR( left_shiftable, << )
358 BOOST_BINARY_OPERATOR( right_shiftable, >> )
360 #undef BOOST_BINARY_OPERATOR
362 template <class T, class U, class B = operators_detail::empty_base<T> >
363 struct equivalent2 : B
365 friend bool operator==(const T& x, const U& y)
367 return !static_cast<bool>(x < y) && !static_cast<bool>(x > y);
371 template <class T, class B = operators_detail::empty_base<T> >
372 struct equivalent1 : B
374 friend bool operator==(const T&x, const T&y)
376 return !static_cast<bool>(x < y) && !static_cast<bool>(y < x);
380 template <class T, class U, class B = operators_detail::empty_base<T> >
381 struct partially_ordered2 : B
383 friend bool operator<=(const T& x, const U& y)
384 { return static_cast<bool>(x < y) || static_cast<bool>(x == y); }
385 friend bool operator>=(const T& x, const U& y)
386 { return static_cast<bool>(x > y) || static_cast<bool>(x == y); }
387 friend bool operator>(const U& x, const T& y)
389 friend bool operator<(const U& x, const T& y)
391 friend bool operator<=(const U& x, const T& y)
392 { return static_cast<bool>(y > x) || static_cast<bool>(y == x); }
393 friend bool operator>=(const U& x, const T& y)
394 { return static_cast<bool>(y < x) || static_cast<bool>(y == x); }
397 template <class T, class B = operators_detail::empty_base<T> >
398 struct partially_ordered1 : B
400 friend bool operator>(const T& x, const T& y)
402 friend bool operator<=(const T& x, const T& y)
403 { return static_cast<bool>(x < y) || static_cast<bool>(x == y); }
404 friend bool operator>=(const T& x, const T& y)
405 { return static_cast<bool>(y < x) || static_cast<bool>(x == y); }
408 // Combined operator classes (contributed by Daryle Walker) ----------------//
410 template <class T, class U, class B = operators_detail::empty_base<T> >
411 struct totally_ordered2
412 : less_than_comparable2<T, U
413 , equality_comparable2<T, U, B
416 template <class T, class B = operators_detail::empty_base<T> >
417 struct totally_ordered1
418 : less_than_comparable1<T
419 , equality_comparable1<T, B
422 template <class T, class U, class B = operators_detail::empty_base<T> >
425 , subtractable2<T, U, B
428 template <class T, class B = operators_detail::empty_base<T> >
434 template <class T, class U, class B = operators_detail::empty_base<T> >
435 struct multiplicative2
440 template <class T, class B = operators_detail::empty_base<T> >
441 struct multiplicative1
446 template <class T, class U, class B = operators_detail::empty_base<T> >
447 struct integer_multiplicative2
448 : multiplicative2<T, U
452 template <class T, class B = operators_detail::empty_base<T> >
453 struct integer_multiplicative1
458 template <class T, class U, class B = operators_detail::empty_base<T> >
461 , multiplicative2<T, U, B
464 template <class T, class B = operators_detail::empty_base<T> >
467 , multiplicative1<T, B
470 template <class T, class U, class B = operators_detail::empty_base<T> >
471 struct integer_arithmetic2
473 , integer_multiplicative2<T, U, B
476 template <class T, class B = operators_detail::empty_base<T> >
477 struct integer_arithmetic1
479 , integer_multiplicative1<T, B
482 template <class T, class U, class B = operators_detail::empty_base<T> >
489 template <class T, class B = operators_detail::empty_base<T> >
496 template <class T, class B = operators_detail::empty_base<T> >
497 struct unit_steppable
502 template <class T, class U, class B = operators_detail::empty_base<T> >
504 : left_shiftable2<T, U
505 , right_shiftable2<T, U, B
508 template <class T, class B = operators_detail::empty_base<T> >
511 , right_shiftable1<T, B
514 template <class T, class U, class B = operators_detail::empty_base<T> >
515 struct ring_operators2
517 , subtractable2_left<T, U
518 , multipliable2<T, U, B
521 template <class T, class B = operators_detail::empty_base<T> >
522 struct ring_operators1
527 template <class T, class U, class B = operators_detail::empty_base<T> >
528 struct ordered_ring_operators2
529 : ring_operators2<T, U
530 , totally_ordered2<T, U, B
533 template <class T, class B = operators_detail::empty_base<T> >
534 struct ordered_ring_operators1
536 , totally_ordered1<T, B
539 template <class T, class U, class B = operators_detail::empty_base<T> >
540 struct field_operators2
541 : ring_operators2<T, U
543 , dividable2_left<T, U, B
546 template <class T, class B = operators_detail::empty_base<T> >
547 struct field_operators1
552 template <class T, class U, class B = operators_detail::empty_base<T> >
553 struct ordered_field_operators2
554 : field_operators2<T, U
555 , totally_ordered2<T, U, B
558 template <class T, class B = operators_detail::empty_base<T> >
559 struct ordered_field_operators1
561 , totally_ordered1<T, B
564 template <class T, class U, class B = operators_detail::empty_base<T> >
565 struct euclidian_ring_operators2
566 : ring_operators2<T, U
568 , dividable2_left<T, U
570 , modable2_left<T, U, B
573 template <class T, class B = operators_detail::empty_base<T> >
574 struct euclidian_ring_operators1
580 template <class T, class U, class B = operators_detail::empty_base<T> >
581 struct ordered_euclidian_ring_operators2
582 : totally_ordered2<T, U
583 , euclidian_ring_operators2<T, U, B
586 template <class T, class B = operators_detail::empty_base<T> >
587 struct ordered_euclidian_ring_operators1
589 , euclidian_ring_operators1<T, B
592 template <class T, class U, class B = operators_detail::empty_base<T> >
593 struct euclidean_ring_operators2
594 : ring_operators2<T, U
596 , dividable2_left<T, U
598 , modable2_left<T, U, B
601 template <class T, class B = operators_detail::empty_base<T> >
602 struct euclidean_ring_operators1
608 template <class T, class U, class B = operators_detail::empty_base<T> >
609 struct ordered_euclidean_ring_operators2
610 : totally_ordered2<T, U
611 , euclidean_ring_operators2<T, U, B
614 template <class T, class B = operators_detail::empty_base<T> >
615 struct ordered_euclidean_ring_operators1
617 , euclidean_ring_operators1<T, B
620 template <class T, class P, class B = operators_detail::empty_base<T> >
621 struct input_iteratable
622 : equality_comparable1<T
624 , dereferenceable<T, P, B
627 template <class T, class B = operators_detail::empty_base<T> >
628 struct output_iteratable
632 template <class T, class P, class B = operators_detail::empty_base<T> >
633 struct forward_iteratable
634 : input_iteratable<T, P, B
637 template <class T, class P, class B = operators_detail::empty_base<T> >
638 struct bidirectional_iteratable
639 : forward_iteratable<T, P
643 // To avoid repeated derivation from equality_comparable,
644 // which is an indirect base class of bidirectional_iterable,
645 // random_access_iteratable must not be derived from totally_ordered1
646 // but from less_than_comparable1 only. (Helmut Zeisel, 02-Dec-2001)
647 template <class T, class P, class D, class R, class B = operators_detail::empty_base<T> >
648 struct random_access_iteratable
649 : bidirectional_iteratable<T, P
650 , less_than_comparable1<T
652 , indexable<T, D, R, B
657 // Here's where we put it all together, defining the xxxx forms of the templates.
658 // We also define specializations of is_chained_base<> for
659 // the xxxx, xxxx1, and xxxx2 templates.
662 namespace operators_detail
665 // A type parameter is used instead of a plain bool because Borland's compiler
666 // didn't cope well with the more obvious non-type template parameter.
670 } // namespace operators_detail
672 // is_chained_base<> - a traits class used to distinguish whether an operator
673 // template argument is being used for base class chaining, or is specifying a
674 // 2nd argument type.
676 // Unspecialized version assumes that most types are not being used for base
677 // class chaining. We specialize for the operator templates defined in this
679 template<class T> struct is_chained_base {
680 typedef operators_detail::false_t value;
683 // Provide a specialization of 'is_chained_base<>'
684 // for a 4-type-argument operator template.
685 # define BOOST_OPERATOR_TEMPLATE4(template_name4) \
686 template<class T, class U, class V, class W, class B> \
687 struct is_chained_base< template_name4<T, U, V, W, B> > { \
688 typedef operators_detail::true_t value; \
691 // Provide a specialization of 'is_chained_base<>'
692 // for a 3-type-argument operator template.
693 # define BOOST_OPERATOR_TEMPLATE3(template_name3) \
694 template<class T, class U, class V, class B> \
695 struct is_chained_base< template_name3<T, U, V, B> > { \
696 typedef operators_detail::true_t value; \
699 // Provide a specialization of 'is_chained_base<>'
700 // for a 2-type-argument operator template.
701 # define BOOST_OPERATOR_TEMPLATE2(template_name2) \
702 template<class T, class U, class B> \
703 struct is_chained_base< template_name2<T, U, B> > { \
704 typedef operators_detail::true_t value; \
707 // Provide a specialization of 'is_chained_base<>'
708 // for a 1-type-argument operator template.
709 # define BOOST_OPERATOR_TEMPLATE1(template_name1) \
710 template<class T, class B> \
711 struct is_chained_base< template_name1<T, B> > { \
712 typedef operators_detail::true_t value; \
715 // BOOST_OPERATOR_TEMPLATE(template_name) defines template_name<> such that it
716 // can be used for specifying both 1-argument and 2-argument forms. Requires the
717 // existence of two previously defined class templates named '<template_name>1'
718 // and '<template_name>2' which must implement the corresponding 1- and 2-
721 // The template type parameter O == is_chained_base<U>::value is used to
722 // distinguish whether the 2nd argument to <template_name> is being used for
723 // base class chaining from another boost operator template or is describing a
724 // 2nd operand type. O == true_t only when U is actually an another operator
725 // template from the library. Partial specialization is used to select an
726 // implementation in terms of either '<template_name>1' or '<template_name>2'.
729 # define BOOST_OPERATOR_TEMPLATE(template_name) \
732 ,class B = operators_detail::empty_base<T> \
733 ,class O = typename is_chained_base<U>::value \
735 struct template_name; \
737 template<class T, class U, class B> \
738 struct template_name<T, U, B, operators_detail::false_t> \
739 : template_name##2<T, U, B> {}; \
741 template<class T, class U> \
742 struct template_name<T, U, operators_detail::empty_base<T>, operators_detail::true_t> \
743 : template_name##1<T, U> {}; \
745 template <class T, class B> \
746 struct template_name<T, T, B, operators_detail::false_t> \
747 : template_name##1<T, B> {}; \
749 template<class T, class U, class B, class O> \
750 struct is_chained_base< template_name<T, U, B, O> > { \
751 typedef operators_detail::true_t value; \
754 BOOST_OPERATOR_TEMPLATE2(template_name##2) \
755 BOOST_OPERATOR_TEMPLATE1(template_name##1)
757 BOOST_OPERATOR_TEMPLATE(less_than_comparable)
758 BOOST_OPERATOR_TEMPLATE(equality_comparable)
759 BOOST_OPERATOR_TEMPLATE(multipliable)
760 BOOST_OPERATOR_TEMPLATE(addable)
761 BOOST_OPERATOR_TEMPLATE(subtractable)
762 BOOST_OPERATOR_TEMPLATE2(subtractable2_left)
763 BOOST_OPERATOR_TEMPLATE(dividable)
764 BOOST_OPERATOR_TEMPLATE2(dividable2_left)
765 BOOST_OPERATOR_TEMPLATE(modable)
766 BOOST_OPERATOR_TEMPLATE2(modable2_left)
767 BOOST_OPERATOR_TEMPLATE(xorable)
768 BOOST_OPERATOR_TEMPLATE(andable)
769 BOOST_OPERATOR_TEMPLATE(orable)
771 BOOST_OPERATOR_TEMPLATE1(incrementable)
772 BOOST_OPERATOR_TEMPLATE1(decrementable)
774 BOOST_OPERATOR_TEMPLATE2(dereferenceable)
775 BOOST_OPERATOR_TEMPLATE3(indexable)
777 BOOST_OPERATOR_TEMPLATE(left_shiftable)
778 BOOST_OPERATOR_TEMPLATE(right_shiftable)
779 BOOST_OPERATOR_TEMPLATE(equivalent)
780 BOOST_OPERATOR_TEMPLATE(partially_ordered)
782 BOOST_OPERATOR_TEMPLATE(totally_ordered)
783 BOOST_OPERATOR_TEMPLATE(additive)
784 BOOST_OPERATOR_TEMPLATE(multiplicative)
785 BOOST_OPERATOR_TEMPLATE(integer_multiplicative)
786 BOOST_OPERATOR_TEMPLATE(arithmetic)
787 BOOST_OPERATOR_TEMPLATE(integer_arithmetic)
788 BOOST_OPERATOR_TEMPLATE(bitwise)
789 BOOST_OPERATOR_TEMPLATE1(unit_steppable)
790 BOOST_OPERATOR_TEMPLATE(shiftable)
791 BOOST_OPERATOR_TEMPLATE(ring_operators)
792 BOOST_OPERATOR_TEMPLATE(ordered_ring_operators)
793 BOOST_OPERATOR_TEMPLATE(field_operators)
794 BOOST_OPERATOR_TEMPLATE(ordered_field_operators)
795 BOOST_OPERATOR_TEMPLATE(euclidian_ring_operators)
796 BOOST_OPERATOR_TEMPLATE(ordered_euclidian_ring_operators)
797 BOOST_OPERATOR_TEMPLATE(euclidean_ring_operators)
798 BOOST_OPERATOR_TEMPLATE(ordered_euclidean_ring_operators)
799 BOOST_OPERATOR_TEMPLATE2(input_iteratable)
800 BOOST_OPERATOR_TEMPLATE1(output_iteratable)
801 BOOST_OPERATOR_TEMPLATE2(forward_iteratable)
802 BOOST_OPERATOR_TEMPLATE2(bidirectional_iteratable)
803 BOOST_OPERATOR_TEMPLATE4(random_access_iteratable)
805 #undef BOOST_OPERATOR_TEMPLATE
806 #undef BOOST_OPERATOR_TEMPLATE4
807 #undef BOOST_OPERATOR_TEMPLATE3
808 #undef BOOST_OPERATOR_TEMPLATE2
809 #undef BOOST_OPERATOR_TEMPLATE1
811 template <class T, class U>
813 : totally_ordered2<T,U
814 , integer_arithmetic2<T,U
818 template <class T, class U = T>
819 struct operators : operators2<T, U> {};
821 template <class T> struct operators<T, T>
823 , integer_arithmetic<T
828 // Iterator helper classes (contributed by Jeremy Siek) -------------------//
829 // (Input and output iterator helpers contributed by Daryle Walker) -------//
830 // (Changed to use combined operator classes by Daryle Walker) ------------//
831 // (Adapted to C++17 by Daniel Frey) --------------------------------------//
832 template <class Category,
834 class Distance = std::ptrdiff_t,
836 class Reference = T&>
837 struct iterator_helper
839 typedef Category iterator_category;
840 typedef T value_type;
841 typedef Distance difference_type;
842 typedef Pointer pointer;
843 typedef Reference reference;
848 class D = std::ptrdiff_t,
851 struct input_iterator_helper
852 : input_iteratable<T, P
853 , iterator_helper<std::input_iterator_tag, V, D, P, R
857 struct output_iterator_helper
858 : output_iteratable<T
859 , iterator_helper<std::output_iterator_tag, void, void, void, void
862 T& operator*() { return static_cast<T&>(*this); }
863 T& operator++() { return static_cast<T&>(*this); }
868 class D = std::ptrdiff_t,
871 struct forward_iterator_helper
872 : forward_iteratable<T, P
873 , iterator_helper<std::forward_iterator_tag, V, D, P, R
878 class D = std::ptrdiff_t,
881 struct bidirectional_iterator_helper
882 : bidirectional_iteratable<T, P
883 , iterator_helper<std::bidirectional_iterator_tag, V, D, P, R
888 class D = std::ptrdiff_t,
891 struct random_access_iterator_helper
892 : random_access_iteratable<T, P, D, R
893 , iterator_helper<std::random_access_iterator_tag, V, D, P, R
896 friend D requires_difference_operator(const T& x, const T& y) {
899 }; // random_access_iterator_helper
901 } // namespace operators_impl
902 using namespace operators_impl;
906 #if defined(__sgi) && !defined(__GNUC__)
907 #pragma reset woff 1234
910 #endif // BOOST_NO_OPERATORS_IN_NAMESPACE
911 #endif // BOOST_OPERATORS_HPP