1 //  Boost operators.hpp header file  ----------------------------------------//
2 
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)
8 
9 //  See http://www.boost.org/libs/utility/operators.htm for documentation.
10 
11 //  Revision History
12 //  23 Nov 17 Protect dereferenceable<> from overloaded operator&.
13 //  15 Oct 17 Adapted to C++17, replace std::iterator<> with manual
14 //            implementation.
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
47 //            Dave Abrahams)
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
51 //            (Mark Rodgers)
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
55 //            for the details.
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
67 
68 // 10 Jun 00:
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.
77 //
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.
83 //
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.
87 
88 #ifndef BOOST_OPERATORS_HPP
89 #define BOOST_OPERATORS_HPP
90 
91 // If old work-arounds are needed, refer to the preserved version without
92 // ADL protection.
93 #if defined(BOOST_NO_OPERATORS_IN_NAMESPACE) || defined(BOOST_USE_OPERATORS_V1)
94 #include "operators_v1.hpp"
95 #else
96 
97 #include <cstddef>
98 #include <iterator>
99 
100 #include <boost/config.hpp>
101 #include <boost/detail/workaround.hpp>
102 #include <boost/core/addressof.hpp>
103 
104 #if defined(__sgi) && !defined(__GNUC__)
105 #   pragma set woff 1234
106 #endif
107 
108 #if BOOST_WORKAROUND(BOOST_MSVC, < 1600)
109 #   pragma warning( disable : 4284 ) // complaint about return type of
110 #endif                               // operator-> not begin a UDT
111 
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.
115 
116 namespace boost
117 {
118 namespace operators_impl
119 {
120 namespace operators_detail
121 {
122 
123 template <typename T> class empty_base {};
124 
125 } // namespace operators_detail
126 
127 //  Basic operator classes (contributed by Dave Abrahams) ------------------//
128 
129 //  Note that friend functions defined in a class are implicitly inline.
130 //  See the C++ std, 11.4 [class.friend] paragraph 5
131 
132 template <class T, class U, class B = operators_detail::empty_base<T> >
133 struct less_than_comparable2 : B
134 {
operator <=(const T & x,const U & y)135      friend bool operator<=(const T& x, const U& y) { return !static_cast<bool>(x > y); }
operator >=(const T & x,const U & y)136      friend bool operator>=(const T& x, const U& y) { return !static_cast<bool>(x < y); }
operator >(const U & x,const T & y)137      friend bool operator>(const U& x, const T& y)  { return y < x; }
operator <(const U & x,const T & y)138      friend bool operator<(const U& x, const T& y)  { return y > x; }
operator <=(const U & x,const T & y)139      friend bool operator<=(const U& x, const T& y) { return !static_cast<bool>(y < x); }
operator >=(const U & x,const T & y)140      friend bool operator>=(const U& x, const T& y) { return !static_cast<bool>(y > x); }
141 };
142 
143 template <class T, class B = operators_detail::empty_base<T> >
144 struct less_than_comparable1 : B
145 {
operator >(const T & x,const T & y)146      friend bool operator>(const T& x, const T& y)  { return y < x; }
operator <=(const T & x,const T & y)147      friend bool operator<=(const T& x, const T& y) { return !static_cast<bool>(y < x); }
operator >=(const T & x,const T & y)148      friend bool operator>=(const T& x, const T& y) { return !static_cast<bool>(x < y); }
149 };
150 
151 template <class T, class U, class B = operators_detail::empty_base<T> >
152 struct equality_comparable2 : B
153 {
operator ==(const U & y,const T & x)154      friend bool operator==(const U& y, const T& x) { return x == y; }
operator !=(const U & y,const T & x)155      friend bool operator!=(const U& y, const T& x) { return !static_cast<bool>(x == y); }
operator !=(const T & y,const U & x)156      friend bool operator!=(const T& y, const U& x) { return !static_cast<bool>(y == x); }
157 };
158 
159 template <class T, class B = operators_detail::empty_base<T> >
160 struct equality_comparable1 : B
161 {
operator !=(const T & x,const T & y)162      friend bool operator!=(const T& x, const T& y) { return !static_cast<bool>(x == y); }
163 };
164 
165 // A macro which produces "name_2left" from "name".
166 #define BOOST_OPERATOR2_LEFT(name) name##2##_##left
167 
168 //  NRVO-friendly implementation (contributed by Daniel Frey) ---------------//
169 
170 #if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
171 
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.
176 
177 #define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP )                   \
178 template <class T, class U, class B = operators_detail::empty_base<T> > \
179 struct NAME##2 : B                                                      \
180 {                                                                       \
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; }                        \
185 };                                                                      \
186                                                                         \
187 template <class T, class B = operators_detail::empty_base<T> >          \
188 struct NAME##1 : B                                                      \
189 {                                                                       \
190   friend T operator OP( const T& lhs, const T& rhs )                    \
191     { T nrv( lhs ); nrv OP##= rhs; return nrv; }                        \
192 };
193 
194 #define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP )               \
195 template <class T, class U, class B = operators_detail::empty_base<T> > \
196 struct NAME##2 : B                                                      \
197 {                                                                       \
198   friend T operator OP( const T& lhs, const U& rhs )                    \
199     { T nrv( lhs ); nrv OP##= rhs; return nrv; }                        \
200 };                                                                      \
201                                                                         \
202 template <class T, class U, class B = operators_detail::empty_base<T> > \
203 struct BOOST_OPERATOR2_LEFT(NAME) : B                                   \
204 {                                                                       \
205   friend T operator OP( const U& lhs, const T& rhs )                    \
206     { T nrv( lhs ); nrv OP##= rhs; return nrv; }                        \
207 };                                                                      \
208                                                                         \
209 template <class T, class B = operators_detail::empty_base<T> >          \
210 struct NAME##1 : B                                                      \
211 {                                                                       \
212   friend T operator OP( const T& lhs, const T& rhs )                    \
213     { T nrv( lhs ); nrv OP##= rhs; return nrv; }                        \
214 };
215 
216 #else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
217 
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 :)
222 
223 #define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP )                   \
224 template <class T, class U, class B = operators_detail::empty_base<T> > \
225 struct NAME##2 : B                                                      \
226 {                                                                       \
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; } \
229 };                                                                      \
230                                                                         \
231 template <class T, class B = operators_detail::empty_base<T> >          \
232 struct NAME##1 : B                                                      \
233 {                                                                       \
234   friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
235 };
236 
237 #define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP )               \
238 template <class T, class U, class B = operators_detail::empty_base<T> > \
239 struct NAME##2 : B                                                      \
240 {                                                                       \
241   friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
242 };                                                                      \
243                                                                         \
244 template <class T, class U, class B = operators_detail::empty_base<T> > \
245 struct BOOST_OPERATOR2_LEFT(NAME) : B                                   \
246 {                                                                       \
247   friend T operator OP( const U& lhs, const T& rhs )                    \
248     { return T( lhs ) OP##= rhs; }                                      \
249 };                                                                      \
250                                                                         \
251 template <class T, class B = operators_detail::empty_base<T> >          \
252 struct NAME##1 : B                                                      \
253 {                                                                       \
254   friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
255 };
256 
257 #endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
258 
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, | )
267 
268 #undef BOOST_BINARY_OPERATOR_COMMUTATIVE
269 #undef BOOST_BINARY_OPERATOR_NON_COMMUTATIVE
270 #undef BOOST_OPERATOR2_LEFT
271 
272 //  incrementable and decrementable contributed by Jeremy Siek
273 
274 template <class T, class B = operators_detail::empty_base<T> >
275 struct incrementable : B
276 {
operator ++(T & x,int)277   friend T operator++(T& x, int)
278   {
279     incrementable_type nrv(x);
280     ++x;
281     return nrv;
282   }
283 private: // The use of this typedef works around a Borland bug
284   typedef T incrementable_type;
285 };
286 
287 template <class T, class B = operators_detail::empty_base<T> >
288 struct decrementable : B
289 {
operator --(T & x,int)290   friend T operator--(T& x, int)
291   {
292     decrementable_type nrv(x);
293     --x;
294     return nrv;
295   }
296 private: // The use of this typedef works around a Borland bug
297   typedef T decrementable_type;
298 };
299 
300 //  Iterator operator classes (contributed by Jeremy Siek) ------------------//
301 
302 template <class T, class P, class B = operators_detail::empty_base<T> >
303 struct dereferenceable : B
304 {
operator ->boost::operators_impl::dereferenceable305   P operator->() const
306   {
307     return ::boost::addressof(*static_cast<const T&>(*this));
308   }
309 };
310 
311 template <class T, class I, class R, class B = operators_detail::empty_base<T> >
312 struct indexable : B
313 {
operator []boost::operators_impl::indexable314   R operator[](I n) const
315   {
316     return *(static_cast<const T&>(*this) + n);
317   }
318 };
319 
320 //  More operator classes (contributed by Daryle Walker) --------------------//
321 //  (NRVO-friendly implementation contributed by Daniel Frey) ---------------//
322 
323 #if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
324 
325 #define BOOST_BINARY_OPERATOR( NAME, OP )                               \
326 template <class T, class U, class B = operators_detail::empty_base<T> > \
327 struct NAME##2 : B                                                      \
328 {                                                                       \
329   friend T operator OP( const T& lhs, const U& rhs )                    \
330     { T nrv( lhs ); nrv OP##= rhs; return nrv; }                        \
331 };                                                                      \
332                                                                         \
333 template <class T, class B = operators_detail::empty_base<T> >          \
334 struct NAME##1 : B                                                      \
335 {                                                                       \
336   friend T operator OP( const T& lhs, const T& rhs )                    \
337     { T nrv( lhs ); nrv OP##= rhs; return nrv; }                        \
338 };
339 
340 #else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
341 
342 #define BOOST_BINARY_OPERATOR( NAME, OP )                               \
343 template <class T, class U, class B = operators_detail::empty_base<T> > \
344 struct NAME##2 : B                                                      \
345 {                                                                       \
346   friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
347 };                                                                      \
348                                                                         \
349 template <class T, class B = operators_detail::empty_base<T> >          \
350 struct NAME##1 : B                                                      \
351 {                                                                       \
352   friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
353 };
354 
355 #endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
356 
357 BOOST_BINARY_OPERATOR( left_shiftable, << )
358 BOOST_BINARY_OPERATOR( right_shiftable, >> )
359 
360 #undef BOOST_BINARY_OPERATOR
361 
362 template <class T, class U, class B = operators_detail::empty_base<T> >
363 struct equivalent2 : B
364 {
operator ==(const T & x,const U & y)365   friend bool operator==(const T& x, const U& y)
366   {
367     return !static_cast<bool>(x < y) && !static_cast<bool>(x > y);
368   }
369 };
370 
371 template <class T, class B = operators_detail::empty_base<T> >
372 struct equivalent1 : B
373 {
operator ==(const T & x,const T & y)374   friend bool operator==(const T&x, const T&y)
375   {
376     return !static_cast<bool>(x < y) && !static_cast<bool>(y < x);
377   }
378 };
379 
380 template <class T, class U, class B = operators_detail::empty_base<T> >
381 struct partially_ordered2 : B
382 {
operator <=(const T & x,const U & y)383   friend bool operator<=(const T& x, const U& y)
384     { return static_cast<bool>(x < y) || static_cast<bool>(x == y); }
operator >=(const T & x,const U & y)385   friend bool operator>=(const T& x, const U& y)
386     { return static_cast<bool>(x > y) || static_cast<bool>(x == y); }
operator >(const U & x,const T & y)387   friend bool operator>(const U& x, const T& y)
388     { return y < x; }
operator <(const U & x,const T & y)389   friend bool operator<(const U& x, const T& y)
390     { return y > x; }
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); }
operator >=(const U & x,const T & y)393   friend bool operator>=(const U& x, const T& y)
394     { return static_cast<bool>(y < x) || static_cast<bool>(y == x); }
395 };
396 
397 template <class T, class B = operators_detail::empty_base<T> >
398 struct partially_ordered1 : B
399 {
operator >(const T & x,const T & y)400   friend bool operator>(const T& x, const T& y)
401     { return y < x; }
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); }
operator >=(const T & x,const T & y)404   friend bool operator>=(const T& x, const T& y)
405     { return static_cast<bool>(y < x) || static_cast<bool>(x == y); }
406 };
407 
408 //  Combined operator classes (contributed by Daryle Walker) ----------------//
409 
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
414       > > {};
415 
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
420       > > {};
421 
422 template <class T, class U, class B = operators_detail::empty_base<T> >
423 struct additive2
424     : addable2<T, U
425     , subtractable2<T, U, B
426       > > {};
427 
428 template <class T, class B = operators_detail::empty_base<T> >
429 struct additive1
430     : addable1<T
431     , subtractable1<T, B
432       > > {};
433 
434 template <class T, class U, class B = operators_detail::empty_base<T> >
435 struct multiplicative2
436     : multipliable2<T, U
437     , dividable2<T, U, B
438       > > {};
439 
440 template <class T, class B = operators_detail::empty_base<T> >
441 struct multiplicative1
442     : multipliable1<T
443     , dividable1<T, B
444       > > {};
445 
446 template <class T, class U, class B = operators_detail::empty_base<T> >
447 struct integer_multiplicative2
448     : multiplicative2<T, U
449     , modable2<T, U, B
450       > > {};
451 
452 template <class T, class B = operators_detail::empty_base<T> >
453 struct integer_multiplicative1
454     : multiplicative1<T
455     , modable1<T, B
456       > > {};
457 
458 template <class T, class U, class B = operators_detail::empty_base<T> >
459 struct arithmetic2
460     : additive2<T, U
461     , multiplicative2<T, U, B
462       > > {};
463 
464 template <class T, class B = operators_detail::empty_base<T> >
465 struct arithmetic1
466     : additive1<T
467     , multiplicative1<T, B
468       > > {};
469 
470 template <class T, class U, class B = operators_detail::empty_base<T> >
471 struct integer_arithmetic2
472     : additive2<T, U
473     , integer_multiplicative2<T, U, B
474       > > {};
475 
476 template <class T, class B = operators_detail::empty_base<T> >
477 struct integer_arithmetic1
478     : additive1<T
479     , integer_multiplicative1<T, B
480       > > {};
481 
482 template <class T, class U, class B = operators_detail::empty_base<T> >
483 struct bitwise2
484     : xorable2<T, U
485     , andable2<T, U
486     , orable2<T, U, B
487       > > > {};
488 
489 template <class T, class B = operators_detail::empty_base<T> >
490 struct bitwise1
491     : xorable1<T
492     , andable1<T
493     , orable1<T, B
494       > > > {};
495 
496 template <class T, class B = operators_detail::empty_base<T> >
497 struct unit_steppable
498     : incrementable<T
499     , decrementable<T, B
500       > > {};
501 
502 template <class T, class U, class B = operators_detail::empty_base<T> >
503 struct shiftable2
504     : left_shiftable2<T, U
505     , right_shiftable2<T, U, B
506       > > {};
507 
508 template <class T, class B = operators_detail::empty_base<T> >
509 struct shiftable1
510     : left_shiftable1<T
511     , right_shiftable1<T, B
512       > > {};
513 
514 template <class T, class U, class B = operators_detail::empty_base<T> >
515 struct ring_operators2
516     : additive2<T, U
517     , subtractable2_left<T, U
518     , multipliable2<T, U, B
519       > > > {};
520 
521 template <class T, class B = operators_detail::empty_base<T> >
522 struct ring_operators1
523     : additive1<T
524     , multipliable1<T, B
525       > > {};
526 
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
531       > > {};
532 
533 template <class T, class B = operators_detail::empty_base<T> >
534 struct ordered_ring_operators1
535     : ring_operators1<T
536     , totally_ordered1<T, B
537       > > {};
538 
539 template <class T, class U, class B = operators_detail::empty_base<T> >
540 struct field_operators2
541     : ring_operators2<T, U
542     , dividable2<T, U
543     , dividable2_left<T, U, B
544       > > > {};
545 
546 template <class T, class B = operators_detail::empty_base<T> >
547 struct field_operators1
548     : ring_operators1<T
549     , dividable1<T, B
550       > > {};
551 
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
556       > > {};
557 
558 template <class T, class B = operators_detail::empty_base<T> >
559 struct ordered_field_operators1
560     : field_operators1<T
561     , totally_ordered1<T, B
562       > > {};
563 
564 template <class T, class U, class B = operators_detail::empty_base<T> >
565 struct euclidian_ring_operators2
566     : ring_operators2<T, U
567     , dividable2<T, U
568     , dividable2_left<T, U
569     , modable2<T, U
570     , modable2_left<T, U, B
571       > > > > > {};
572 
573 template <class T, class B = operators_detail::empty_base<T> >
574 struct euclidian_ring_operators1
575     : ring_operators1<T
576     , dividable1<T
577     , modable1<T, B
578       > > > {};
579 
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
584       > > {};
585 
586 template <class T, class B = operators_detail::empty_base<T> >
587 struct ordered_euclidian_ring_operators1
588     : totally_ordered1<T
589     , euclidian_ring_operators1<T, B
590       > > {};
591 
592 template <class T, class U, class B = operators_detail::empty_base<T> >
593 struct euclidean_ring_operators2
594     : ring_operators2<T, U
595     , dividable2<T, U
596     , dividable2_left<T, U
597     , modable2<T, U
598     , modable2_left<T, U, B
599       > > > > > {};
600 
601 template <class T, class B = operators_detail::empty_base<T> >
602 struct euclidean_ring_operators1
603     : ring_operators1<T
604     , dividable1<T
605     , modable1<T, B
606       > > > {};
607 
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
612       > > {};
613 
614 template <class T, class B = operators_detail::empty_base<T> >
615 struct ordered_euclidean_ring_operators1
616     : totally_ordered1<T
617     , euclidean_ring_operators1<T, B
618       > > {};
619 
620 template <class T, class P, class B = operators_detail::empty_base<T> >
621 struct input_iteratable
622     : equality_comparable1<T
623     , incrementable<T
624     , dereferenceable<T, P, B
625       > > > {};
626 
627 template <class T, class B = operators_detail::empty_base<T> >
628 struct output_iteratable
629     : incrementable<T, B
630       > {};
631 
632 template <class T, class P, class B = operators_detail::empty_base<T> >
633 struct forward_iteratable
634     : input_iteratable<T, P, B
635       > {};
636 
637 template <class T, class P, class B = operators_detail::empty_base<T> >
638 struct bidirectional_iteratable
639     : forward_iteratable<T, P
640     , decrementable<T, B
641       > > {};
642 
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
651     , additive2<T, D
652     , indexable<T, D, R, B
653       > > > > {};
654 
655 
656 //
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.
660 //
661 
662 namespace operators_detail
663 {
664 
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.
667 struct true_t {};
668 struct false_t {};
669 
670 } // namespace operators_detail
671 
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.
675 
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
678 // library.
679 template<class T> struct is_chained_base {
680   typedef operators_detail::false_t value;
681 };
682 
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;                 \
689   };
690 
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;              \
697   };
698 
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;           \
705   };
706 
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;        \
713   };
714 
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-
719 // argument forms.
720 //
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'.
727 //
728 
729 # define BOOST_OPERATOR_TEMPLATE(template_name)                                       \
730 template <class T                                                                     \
731          ,class U = T                                                                 \
732          ,class B = operators_detail::empty_base<T>                                   \
733          ,class O = typename is_chained_base<U>::value                                \
734          >                                                                            \
735 struct template_name;                                                                 \
736                                                                                       \
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> {};                                                     \
740                                                                                       \
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> {};                                                        \
744                                                                                       \
745 template <class T, class B>                                                           \
746 struct template_name<T, T, B, operators_detail::false_t>                              \
747   : template_name##1<T, B> {};                                                        \
748                                                                                       \
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;                                             \
752 };                                                                                    \
753                                                                                       \
754 BOOST_OPERATOR_TEMPLATE2(template_name##2)                                            \
755 BOOST_OPERATOR_TEMPLATE1(template_name##1)
756 
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)
770 
771 BOOST_OPERATOR_TEMPLATE1(incrementable)
772 BOOST_OPERATOR_TEMPLATE1(decrementable)
773 
774 BOOST_OPERATOR_TEMPLATE2(dereferenceable)
775 BOOST_OPERATOR_TEMPLATE3(indexable)
776 
777 BOOST_OPERATOR_TEMPLATE(left_shiftable)
778 BOOST_OPERATOR_TEMPLATE(right_shiftable)
779 BOOST_OPERATOR_TEMPLATE(equivalent)
780 BOOST_OPERATOR_TEMPLATE(partially_ordered)
781 
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)
804 
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
810 
811 template <class T, class U>
812 struct operators2
813     : totally_ordered2<T,U
814     , integer_arithmetic2<T,U
815     , bitwise2<T,U
816       > > > {};
817 
818 template <class T, class U = T>
819 struct operators : operators2<T, U> {};
820 
821 template <class T> struct operators<T, T>
822     : totally_ordered<T
823     , integer_arithmetic<T
824     , bitwise<T
825     , unit_steppable<T
826       > > > > {};
827 
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,
833           class T,
834           class Distance = std::ptrdiff_t,
835           class Pointer = T*,
836           class Reference = T&>
837 struct iterator_helper
838 {
839   typedef Category iterator_category;
840   typedef T value_type;
841   typedef Distance difference_type;
842   typedef Pointer pointer;
843   typedef Reference reference;
844 };
845 
846 template <class T,
847           class V,
848           class D = std::ptrdiff_t,
849           class P = V const *,
850           class R = V const &>
851 struct input_iterator_helper
852   : input_iteratable<T, P
853   , iterator_helper<std::input_iterator_tag, V, D, P, R
854     > > {};
855 
856 template<class T>
857 struct output_iterator_helper
858   : output_iteratable<T
859   , iterator_helper<std::output_iterator_tag, void, void, void, void
860   > >
861 {
operator *boost::operators_impl::output_iterator_helper862   T& operator*()  { return static_cast<T&>(*this); }
operator ++boost::operators_impl::output_iterator_helper863   T& operator++() { return static_cast<T&>(*this); }
864 };
865 
866 template <class T,
867           class V,
868           class D = std::ptrdiff_t,
869           class P = V*,
870           class R = V&>
871 struct forward_iterator_helper
872   : forward_iteratable<T, P
873   , iterator_helper<std::forward_iterator_tag, V, D, P, R
874     > > {};
875 
876 template <class T,
877           class V,
878           class D = std::ptrdiff_t,
879           class P = V*,
880           class R = V&>
881 struct bidirectional_iterator_helper
882   : bidirectional_iteratable<T, P
883   , iterator_helper<std::bidirectional_iterator_tag, V, D, P, R
884     > > {};
885 
886 template <class T,
887           class V,
888           class D = std::ptrdiff_t,
889           class P = V*,
890           class R = V&>
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
894     > >
895 {
requires_difference_operator(const T & x,const T & y)896   friend D requires_difference_operator(const T& x, const T& y) {
897     return x - y;
898   }
899 }; // random_access_iterator_helper
900 
901 } // namespace operators_impl
902 using namespace operators_impl;
903 
904 } // namespace boost
905 
906 #if defined(__sgi) && !defined(__GNUC__)
907 #pragma reset woff 1234
908 #endif
909 
910 #endif // BOOST_NO_OPERATORS_IN_NAMESPACE
911 #endif // BOOST_OPERATORS_HPP
912