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 // Define BOOST_OPERATORS_CONSTEXPR to be like BOOST_CONSTEXPR but empty under MSVC < v19.22
113 #if BOOST_WORKAROUND(BOOST_MSVC, < 1922)
114 #define BOOST_OPERATORS_CONSTEXPR
115 #else
116 #define BOOST_OPERATORS_CONSTEXPR BOOST_CONSTEXPR
117 #endif
118 
119 // In this section we supply the xxxx1 and xxxx2 forms of the operator
120 // templates, which are explicitly targeted at the 1-type-argument and
121 // 2-type-argument operator forms, respectively.
122 
123 namespace boost
124 {
125 namespace operators_impl
126 {
127 namespace operators_detail
128 {
129 
130 template <typename T> class empty_base {};
131 
132 } // namespace operators_detail
133 
134 //  Basic operator classes (contributed by Dave Abrahams) ------------------//
135 
136 //  Note that friend functions defined in a class are implicitly inline.
137 //  See the C++ std, 11.4 [class.friend] paragraph 5
138 
139 template <class T, class U, class B = operators_detail::empty_base<T> >
140 struct less_than_comparable2 : B
141 {
operator <=(const T & x,const U & y)142      friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const T& x, const U& y) { return !static_cast<bool>(x > y); }
operator >=(const T & x,const U & y)143      friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const T& x, const U& y) { return !static_cast<bool>(x < y); }
operator >(const U & x,const T & y)144      friend BOOST_OPERATORS_CONSTEXPR bool operator>(const U& x, const T& y)  { return y < x; }
operator <(const U & x,const T & y)145      friend BOOST_OPERATORS_CONSTEXPR bool operator<(const U& x, const T& y)  { return y > x; }
operator <=(const U & x,const T & y)146      friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const U& x, const T& y) { return !static_cast<bool>(y < x); }
operator >=(const U & x,const T & y)147      friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const U& x, const T& y) { return !static_cast<bool>(y > x); }
148 };
149 
150 template <class T, class B = operators_detail::empty_base<T> >
151 struct less_than_comparable1 : B
152 {
operator >(const T & x,const T & y)153      friend BOOST_OPERATORS_CONSTEXPR bool operator>(const T& x, const T& y)  { return y < x; }
operator <=(const T & x,const T & y)154      friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const T& x, const T& y) { return !static_cast<bool>(y < x); }
operator >=(const T & x,const T & y)155      friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const T& x, const T& y) { return !static_cast<bool>(x < y); }
156 };
157 
158 template <class T, class U, class B = operators_detail::empty_base<T> >
159 struct equality_comparable2 : B
160 {
operator ==(const U & y,const T & x)161      friend BOOST_OPERATORS_CONSTEXPR bool operator==(const U& y, const T& x) { return x == y; }
operator !=(const U & y,const T & x)162      friend BOOST_OPERATORS_CONSTEXPR bool operator!=(const U& y, const T& x) { return !static_cast<bool>(x == y); }
operator !=(const T & y,const U & x)163      friend BOOST_OPERATORS_CONSTEXPR bool operator!=(const T& y, const U& x) { return !static_cast<bool>(y == x); }
164 };
165 
166 template <class T, class B = operators_detail::empty_base<T> >
167 struct equality_comparable1 : B
168 {
operator !=(const T & x,const T & y)169      friend BOOST_OPERATORS_CONSTEXPR bool operator!=(const T& x, const T& y) { return !static_cast<bool>(x == y); }
170 };
171 
172 // A macro which produces "name_2left" from "name".
173 #define BOOST_OPERATOR2_LEFT(name) name##2##_##left
174 
175 //  NRVO-friendly implementation (contributed by Daniel Frey) ---------------//
176 
177 #if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
178 
179 // This is the optimal implementation for ISO/ANSI C++,
180 // but it requires the compiler to implement the NRVO.
181 // If the compiler has no NRVO, this is the best symmetric
182 // implementation available.
183 
184 #define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP )                   \
185 template <class T, class U, class B = operators_detail::empty_base<T> > \
186 struct NAME##2 : B                                                      \
187 {                                                                       \
188   friend T operator OP( const T& lhs, const U& rhs )                    \
189     { T nrv( lhs ); nrv OP##= rhs; return nrv; }                        \
190   friend T operator OP( const U& lhs, const T& rhs )                    \
191     { T nrv( rhs ); nrv OP##= lhs; return nrv; }                        \
192 };                                                                      \
193                                                                         \
194 template <class T, class B = operators_detail::empty_base<T> >          \
195 struct NAME##1 : B                                                      \
196 {                                                                       \
197   friend T operator OP( const T& lhs, const T& rhs )                    \
198     { T nrv( lhs ); nrv OP##= rhs; return nrv; }                        \
199 };
200 
201 #define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP )               \
202 template <class T, class U, class B = operators_detail::empty_base<T> > \
203 struct NAME##2 : B                                                      \
204 {                                                                       \
205   friend T operator OP( const T& lhs, const U& rhs )                    \
206     { T nrv( lhs ); nrv OP##= rhs; return nrv; }                        \
207 };                                                                      \
208                                                                         \
209 template <class T, class U, class B = operators_detail::empty_base<T> > \
210 struct BOOST_OPERATOR2_LEFT(NAME) : B                                   \
211 {                                                                       \
212   friend T operator OP( const U& lhs, const T& rhs )                    \
213     { T nrv( lhs ); nrv OP##= rhs; return nrv; }                        \
214 };                                                                      \
215                                                                         \
216 template <class T, class B = operators_detail::empty_base<T> >          \
217 struct NAME##1 : B                                                      \
218 {                                                                       \
219   friend T operator OP( const T& lhs, const T& rhs )                    \
220     { T nrv( lhs ); nrv OP##= rhs; return nrv; }                        \
221 };
222 
223 #else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
224 
225 // For compilers without NRVO the following code is optimal, but not
226 // symmetric!  Note that the implementation of
227 // BOOST_OPERATOR2_LEFT(NAME) only looks cool, but doesn't provide
228 // optimization opportunities to the compiler :)
229 
230 #define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP )                   \
231 template <class T, class U, class B = operators_detail::empty_base<T> > \
232 struct NAME##2 : B                                                      \
233 {                                                                       \
234   friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
235   friend T operator OP( const U& lhs, T rhs ) { return rhs OP##= lhs; } \
236 };                                                                      \
237                                                                         \
238 template <class T, class B = operators_detail::empty_base<T> >          \
239 struct NAME##1 : B                                                      \
240 {                                                                       \
241   friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
242 };
243 
244 #define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP )               \
245 template <class T, class U, class B = operators_detail::empty_base<T> > \
246 struct NAME##2 : B                                                      \
247 {                                                                       \
248   friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
249 };                                                                      \
250                                                                         \
251 template <class T, class U, class B = operators_detail::empty_base<T> > \
252 struct BOOST_OPERATOR2_LEFT(NAME) : B                                   \
253 {                                                                       \
254   friend T operator OP( const U& lhs, const T& rhs )                    \
255     { return T( lhs ) OP##= rhs; }                                      \
256 };                                                                      \
257                                                                         \
258 template <class T, class B = operators_detail::empty_base<T> >          \
259 struct NAME##1 : B                                                      \
260 {                                                                       \
261   friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
262 };
263 
264 #endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
265 
266 BOOST_BINARY_OPERATOR_COMMUTATIVE( multipliable, * )
267 BOOST_BINARY_OPERATOR_COMMUTATIVE( addable, + )
268 BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( subtractable, - )
269 BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( dividable, / )
270 BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( modable, % )
271 BOOST_BINARY_OPERATOR_COMMUTATIVE( xorable, ^ )
272 BOOST_BINARY_OPERATOR_COMMUTATIVE( andable, & )
273 BOOST_BINARY_OPERATOR_COMMUTATIVE( orable, | )
274 
275 #undef BOOST_BINARY_OPERATOR_COMMUTATIVE
276 #undef BOOST_BINARY_OPERATOR_NON_COMMUTATIVE
277 #undef BOOST_OPERATOR2_LEFT
278 
279 //  incrementable and decrementable contributed by Jeremy Siek
280 
281 template <class T, class B = operators_detail::empty_base<T> >
282 struct incrementable : B
283 {
operator ++(T & x,int)284   friend T operator++(T& x, int)
285   {
286     incrementable_type nrv(x);
287     ++x;
288     return nrv;
289   }
290 private: // The use of this typedef works around a Borland bug
291   typedef T incrementable_type;
292 };
293 
294 template <class T, class B = operators_detail::empty_base<T> >
295 struct decrementable : B
296 {
operator --(T & x,int)297   friend T operator--(T& x, int)
298   {
299     decrementable_type nrv(x);
300     --x;
301     return nrv;
302   }
303 private: // The use of this typedef works around a Borland bug
304   typedef T decrementable_type;
305 };
306 
307 //  Iterator operator classes (contributed by Jeremy Siek) ------------------//
308 
309 template <class T, class P, class B = operators_detail::empty_base<T> >
310 struct dereferenceable : B
311 {
operator ->boost::operators_impl::dereferenceable312   P operator->() const
313   {
314     return ::boost::addressof(*static_cast<const T&>(*this));
315   }
316 };
317 
318 template <class T, class I, class R, class B = operators_detail::empty_base<T> >
319 struct indexable : B
320 {
operator []boost::operators_impl::indexable321   R operator[](I n) const
322   {
323     return *(static_cast<const T&>(*this) + n);
324   }
325 };
326 
327 //  More operator classes (contributed by Daryle Walker) --------------------//
328 //  (NRVO-friendly implementation contributed by Daniel Frey) ---------------//
329 
330 #if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
331 
332 #define BOOST_BINARY_OPERATOR( NAME, OP )                               \
333 template <class T, class U, class B = operators_detail::empty_base<T> > \
334 struct NAME##2 : B                                                      \
335 {                                                                       \
336   friend T operator OP( const T& lhs, const U& rhs )                    \
337     { T nrv( lhs ); nrv OP##= rhs; return nrv; }                        \
338 };                                                                      \
339                                                                         \
340 template <class T, class B = operators_detail::empty_base<T> >          \
341 struct NAME##1 : B                                                      \
342 {                                                                       \
343   friend T operator OP( const T& lhs, const T& rhs )                    \
344     { T nrv( lhs ); nrv OP##= rhs; return nrv; }                        \
345 };
346 
347 #else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
348 
349 #define BOOST_BINARY_OPERATOR( NAME, OP )                               \
350 template <class T, class U, class B = operators_detail::empty_base<T> > \
351 struct NAME##2 : B                                                      \
352 {                                                                       \
353   friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
354 };                                                                      \
355                                                                         \
356 template <class T, class B = operators_detail::empty_base<T> >          \
357 struct NAME##1 : B                                                      \
358 {                                                                       \
359   friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
360 };
361 
362 #endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
363 
364 BOOST_BINARY_OPERATOR( left_shiftable, << )
365 BOOST_BINARY_OPERATOR( right_shiftable, >> )
366 
367 #undef BOOST_BINARY_OPERATOR
368 
369 template <class T, class U, class B = operators_detail::empty_base<T> >
370 struct equivalent2 : B
371 {
operator ==(const T & x,const U & y)372   friend BOOST_OPERATORS_CONSTEXPR bool operator==(const T& x, const U& y)
373   {
374     return !static_cast<bool>(x < y) && !static_cast<bool>(x > y);
375   }
376 };
377 
378 template <class T, class B = operators_detail::empty_base<T> >
379 struct equivalent1 : B
380 {
operator ==(const T & x,const T & y)381   friend BOOST_OPERATORS_CONSTEXPR bool operator==(const T&x, const T&y)
382   {
383     return !static_cast<bool>(x < y) && !static_cast<bool>(y < x);
384   }
385 };
386 
387 template <class T, class U, class B = operators_detail::empty_base<T> >
388 struct partially_ordered2 : B
389 {
operator <=(const T & x,const U & y)390   friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const T& x, const U& y)
391     { return static_cast<bool>(x < y) || static_cast<bool>(x == y); }
operator >=(const T & x,const U & y)392   friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const T& x, const U& y)
393     { return static_cast<bool>(x > y) || static_cast<bool>(x == y); }
operator >(const U & x,const T & y)394   friend BOOST_OPERATORS_CONSTEXPR bool operator>(const U& x, const T& y)
395     { return y < x; }
operator <(const U & x,const T & y)396   friend BOOST_OPERATORS_CONSTEXPR bool operator<(const U& x, const T& y)
397     { return y > x; }
operator <=(const U & x,const T & y)398   friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const U& x, const T& y)
399     { return static_cast<bool>(y > x) || static_cast<bool>(y == x); }
operator >=(const U & x,const T & y)400   friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const U& x, const T& y)
401     { return static_cast<bool>(y < x) || static_cast<bool>(y == x); }
402 };
403 
404 template <class T, class B = operators_detail::empty_base<T> >
405 struct partially_ordered1 : B
406 {
operator >(const T & x,const T & y)407   friend BOOST_OPERATORS_CONSTEXPR bool operator>(const T& x, const T& y)
408     { return y < x; }
operator <=(const T & x,const T & y)409   friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const T& x, const T& y)
410     { return static_cast<bool>(x < y) || static_cast<bool>(x == y); }
operator >=(const T & x,const T & y)411   friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const T& x, const T& y)
412     { return static_cast<bool>(y < x) || static_cast<bool>(x == y); }
413 };
414 
415 //  Combined operator classes (contributed by Daryle Walker) ----------------//
416 
417 template <class T, class U, class B = operators_detail::empty_base<T> >
418 struct totally_ordered2
419     : less_than_comparable2<T, U
420     , equality_comparable2<T, U, B
421       > > {};
422 
423 template <class T, class B = operators_detail::empty_base<T> >
424 struct totally_ordered1
425     : less_than_comparable1<T
426     , equality_comparable1<T, B
427       > > {};
428 
429 template <class T, class U, class B = operators_detail::empty_base<T> >
430 struct additive2
431     : addable2<T, U
432     , subtractable2<T, U, B
433       > > {};
434 
435 template <class T, class B = operators_detail::empty_base<T> >
436 struct additive1
437     : addable1<T
438     , subtractable1<T, B
439       > > {};
440 
441 template <class T, class U, class B = operators_detail::empty_base<T> >
442 struct multiplicative2
443     : multipliable2<T, U
444     , dividable2<T, U, B
445       > > {};
446 
447 template <class T, class B = operators_detail::empty_base<T> >
448 struct multiplicative1
449     : multipliable1<T
450     , dividable1<T, B
451       > > {};
452 
453 template <class T, class U, class B = operators_detail::empty_base<T> >
454 struct integer_multiplicative2
455     : multiplicative2<T, U
456     , modable2<T, U, B
457       > > {};
458 
459 template <class T, class B = operators_detail::empty_base<T> >
460 struct integer_multiplicative1
461     : multiplicative1<T
462     , modable1<T, B
463       > > {};
464 
465 template <class T, class U, class B = operators_detail::empty_base<T> >
466 struct arithmetic2
467     : additive2<T, U
468     , multiplicative2<T, U, B
469       > > {};
470 
471 template <class T, class B = operators_detail::empty_base<T> >
472 struct arithmetic1
473     : additive1<T
474     , multiplicative1<T, B
475       > > {};
476 
477 template <class T, class U, class B = operators_detail::empty_base<T> >
478 struct integer_arithmetic2
479     : additive2<T, U
480     , integer_multiplicative2<T, U, B
481       > > {};
482 
483 template <class T, class B = operators_detail::empty_base<T> >
484 struct integer_arithmetic1
485     : additive1<T
486     , integer_multiplicative1<T, B
487       > > {};
488 
489 template <class T, class U, class B = operators_detail::empty_base<T> >
490 struct bitwise2
491     : xorable2<T, U
492     , andable2<T, U
493     , orable2<T, U, B
494       > > > {};
495 
496 template <class T, class B = operators_detail::empty_base<T> >
497 struct bitwise1
498     : xorable1<T
499     , andable1<T
500     , orable1<T, B
501       > > > {};
502 
503 template <class T, class B = operators_detail::empty_base<T> >
504 struct unit_steppable
505     : incrementable<T
506     , decrementable<T, B
507       > > {};
508 
509 template <class T, class U, class B = operators_detail::empty_base<T> >
510 struct shiftable2
511     : left_shiftable2<T, U
512     , right_shiftable2<T, U, B
513       > > {};
514 
515 template <class T, class B = operators_detail::empty_base<T> >
516 struct shiftable1
517     : left_shiftable1<T
518     , right_shiftable1<T, B
519       > > {};
520 
521 template <class T, class U, class B = operators_detail::empty_base<T> >
522 struct ring_operators2
523     : additive2<T, U
524     , subtractable2_left<T, U
525     , multipliable2<T, U, B
526       > > > {};
527 
528 template <class T, class B = operators_detail::empty_base<T> >
529 struct ring_operators1
530     : additive1<T
531     , multipliable1<T, B
532       > > {};
533 
534 template <class T, class U, class B = operators_detail::empty_base<T> >
535 struct ordered_ring_operators2
536     : ring_operators2<T, U
537     , totally_ordered2<T, U, B
538       > > {};
539 
540 template <class T, class B = operators_detail::empty_base<T> >
541 struct ordered_ring_operators1
542     : ring_operators1<T
543     , totally_ordered1<T, B
544       > > {};
545 
546 template <class T, class U, class B = operators_detail::empty_base<T> >
547 struct field_operators2
548     : ring_operators2<T, U
549     , dividable2<T, U
550     , dividable2_left<T, U, B
551       > > > {};
552 
553 template <class T, class B = operators_detail::empty_base<T> >
554 struct field_operators1
555     : ring_operators1<T
556     , dividable1<T, B
557       > > {};
558 
559 template <class T, class U, class B = operators_detail::empty_base<T> >
560 struct ordered_field_operators2
561     : field_operators2<T, U
562     , totally_ordered2<T, U, B
563       > > {};
564 
565 template <class T, class B = operators_detail::empty_base<T> >
566 struct ordered_field_operators1
567     : field_operators1<T
568     , totally_ordered1<T, B
569       > > {};
570 
571 template <class T, class U, class B = operators_detail::empty_base<T> >
572 struct euclidian_ring_operators2
573     : ring_operators2<T, U
574     , dividable2<T, U
575     , dividable2_left<T, U
576     , modable2<T, U
577     , modable2_left<T, U, B
578       > > > > > {};
579 
580 template <class T, class B = operators_detail::empty_base<T> >
581 struct euclidian_ring_operators1
582     : ring_operators1<T
583     , dividable1<T
584     , modable1<T, B
585       > > > {};
586 
587 template <class T, class U, class B = operators_detail::empty_base<T> >
588 struct ordered_euclidian_ring_operators2
589     : totally_ordered2<T, U
590     , euclidian_ring_operators2<T, U, B
591       > > {};
592 
593 template <class T, class B = operators_detail::empty_base<T> >
594 struct ordered_euclidian_ring_operators1
595     : totally_ordered1<T
596     , euclidian_ring_operators1<T, B
597       > > {};
598 
599 template <class T, class U, class B = operators_detail::empty_base<T> >
600 struct euclidean_ring_operators2
601     : ring_operators2<T, U
602     , dividable2<T, U
603     , dividable2_left<T, U
604     , modable2<T, U
605     , modable2_left<T, U, B
606       > > > > > {};
607 
608 template <class T, class B = operators_detail::empty_base<T> >
609 struct euclidean_ring_operators1
610     : ring_operators1<T
611     , dividable1<T
612     , modable1<T, B
613       > > > {};
614 
615 template <class T, class U, class B = operators_detail::empty_base<T> >
616 struct ordered_euclidean_ring_operators2
617     : totally_ordered2<T, U
618     , euclidean_ring_operators2<T, U, B
619       > > {};
620 
621 template <class T, class B = operators_detail::empty_base<T> >
622 struct ordered_euclidean_ring_operators1
623     : totally_ordered1<T
624     , euclidean_ring_operators1<T, B
625       > > {};
626 
627 template <class T, class P, class B = operators_detail::empty_base<T> >
628 struct input_iteratable
629     : equality_comparable1<T
630     , incrementable<T
631     , dereferenceable<T, P, B
632       > > > {};
633 
634 template <class T, class B = operators_detail::empty_base<T> >
635 struct output_iteratable
636     : incrementable<T, B
637       > {};
638 
639 template <class T, class P, class B = operators_detail::empty_base<T> >
640 struct forward_iteratable
641     : input_iteratable<T, P, B
642       > {};
643 
644 template <class T, class P, class B = operators_detail::empty_base<T> >
645 struct bidirectional_iteratable
646     : forward_iteratable<T, P
647     , decrementable<T, B
648       > > {};
649 
650 //  To avoid repeated derivation from equality_comparable,
651 //  which is an indirect base class of bidirectional_iterable,
652 //  random_access_iteratable must not be derived from totally_ordered1
653 //  but from less_than_comparable1 only. (Helmut Zeisel, 02-Dec-2001)
654 template <class T, class P, class D, class R, class B = operators_detail::empty_base<T> >
655 struct random_access_iteratable
656     : bidirectional_iteratable<T, P
657     , less_than_comparable1<T
658     , additive2<T, D
659     , indexable<T, D, R, B
660       > > > > {};
661 
662 
663 //
664 // Here's where we put it all together, defining the xxxx forms of the templates.
665 // We also define specializations of is_chained_base<> for
666 // the xxxx, xxxx1, and xxxx2 templates.
667 //
668 
669 namespace operators_detail
670 {
671 
672 // A type parameter is used instead of a plain bool because Borland's compiler
673 // didn't cope well with the more obvious non-type template parameter.
674 struct true_t {};
675 struct false_t {};
676 
677 } // namespace operators_detail
678 
679 // is_chained_base<> - a traits class used to distinguish whether an operator
680 // template argument is being used for base class chaining, or is specifying a
681 // 2nd argument type.
682 
683 // Unspecialized version assumes that most types are not being used for base
684 // class chaining. We specialize for the operator templates defined in this
685 // library.
686 template<class T> struct is_chained_base {
687   typedef operators_detail::false_t value;
688 };
689 
690 // Provide a specialization of 'is_chained_base<>'
691 // for a 4-type-argument operator template.
692 # define BOOST_OPERATOR_TEMPLATE4(template_name4)           \
693   template<class T, class U, class V, class W, class B>     \
694   struct is_chained_base< template_name4<T, U, V, W, B> > { \
695     typedef operators_detail::true_t value;                 \
696   };
697 
698 // Provide a specialization of 'is_chained_base<>'
699 // for a 3-type-argument operator template.
700 # define BOOST_OPERATOR_TEMPLATE3(template_name3)        \
701   template<class T, class U, class V, class B>           \
702   struct is_chained_base< template_name3<T, U, V, B> > { \
703     typedef operators_detail::true_t value;              \
704   };
705 
706 // Provide a specialization of 'is_chained_base<>'
707 // for a 2-type-argument operator template.
708 # define BOOST_OPERATOR_TEMPLATE2(template_name2)     \
709   template<class T, class U, class B>                 \
710   struct is_chained_base< template_name2<T, U, B> > { \
711     typedef operators_detail::true_t value;           \
712   };
713 
714 // Provide a specialization of 'is_chained_base<>'
715 // for a 1-type-argument operator template.
716 # define BOOST_OPERATOR_TEMPLATE1(template_name1)  \
717   template<class T, class B>                       \
718   struct is_chained_base< template_name1<T, B> > { \
719     typedef operators_detail::true_t value;        \
720   };
721 
722 // BOOST_OPERATOR_TEMPLATE(template_name) defines template_name<> such that it
723 // can be used for specifying both 1-argument and 2-argument forms. Requires the
724 // existence of two previously defined class templates named '<template_name>1'
725 // and '<template_name>2' which must implement the corresponding 1- and 2-
726 // argument forms.
727 //
728 // The template type parameter O == is_chained_base<U>::value is used to
729 // distinguish whether the 2nd argument to <template_name> is being used for
730 // base class chaining from another boost operator template or is describing a
731 // 2nd operand type. O == true_t only when U is actually an another operator
732 // template from the library. Partial specialization is used to select an
733 // implementation in terms of either '<template_name>1' or '<template_name>2'.
734 //
735 
736 # define BOOST_OPERATOR_TEMPLATE(template_name)                                       \
737 template <class T                                                                     \
738          ,class U = T                                                                 \
739          ,class B = operators_detail::empty_base<T>                                   \
740          ,class O = typename is_chained_base<U>::value                                \
741          >                                                                            \
742 struct template_name;                                                                 \
743                                                                                       \
744 template<class T, class U, class B>                                                   \
745 struct template_name<T, U, B, operators_detail::false_t>                              \
746   : template_name##2<T, U, B> {};                                                     \
747                                                                                       \
748 template<class T, class U>                                                            \
749 struct template_name<T, U, operators_detail::empty_base<T>, operators_detail::true_t> \
750   : template_name##1<T, U> {};                                                        \
751                                                                                       \
752 template <class T, class B>                                                           \
753 struct template_name<T, T, B, operators_detail::false_t>                              \
754   : template_name##1<T, B> {};                                                        \
755                                                                                       \
756 template<class T, class U, class B, class O>                                          \
757 struct is_chained_base< template_name<T, U, B, O> > {                                 \
758   typedef operators_detail::true_t value;                                             \
759 };                                                                                    \
760                                                                                       \
761 BOOST_OPERATOR_TEMPLATE2(template_name##2)                                            \
762 BOOST_OPERATOR_TEMPLATE1(template_name##1)
763 
764 BOOST_OPERATOR_TEMPLATE(less_than_comparable)
765 BOOST_OPERATOR_TEMPLATE(equality_comparable)
766 BOOST_OPERATOR_TEMPLATE(multipliable)
767 BOOST_OPERATOR_TEMPLATE(addable)
768 BOOST_OPERATOR_TEMPLATE(subtractable)
769 BOOST_OPERATOR_TEMPLATE2(subtractable2_left)
770 BOOST_OPERATOR_TEMPLATE(dividable)
771 BOOST_OPERATOR_TEMPLATE2(dividable2_left)
772 BOOST_OPERATOR_TEMPLATE(modable)
773 BOOST_OPERATOR_TEMPLATE2(modable2_left)
774 BOOST_OPERATOR_TEMPLATE(xorable)
775 BOOST_OPERATOR_TEMPLATE(andable)
776 BOOST_OPERATOR_TEMPLATE(orable)
777 
778 BOOST_OPERATOR_TEMPLATE1(incrementable)
779 BOOST_OPERATOR_TEMPLATE1(decrementable)
780 
781 BOOST_OPERATOR_TEMPLATE2(dereferenceable)
782 BOOST_OPERATOR_TEMPLATE3(indexable)
783 
784 BOOST_OPERATOR_TEMPLATE(left_shiftable)
785 BOOST_OPERATOR_TEMPLATE(right_shiftable)
786 BOOST_OPERATOR_TEMPLATE(equivalent)
787 BOOST_OPERATOR_TEMPLATE(partially_ordered)
788 
789 BOOST_OPERATOR_TEMPLATE(totally_ordered)
790 BOOST_OPERATOR_TEMPLATE(additive)
791 BOOST_OPERATOR_TEMPLATE(multiplicative)
792 BOOST_OPERATOR_TEMPLATE(integer_multiplicative)
793 BOOST_OPERATOR_TEMPLATE(arithmetic)
794 BOOST_OPERATOR_TEMPLATE(integer_arithmetic)
795 BOOST_OPERATOR_TEMPLATE(bitwise)
796 BOOST_OPERATOR_TEMPLATE1(unit_steppable)
797 BOOST_OPERATOR_TEMPLATE(shiftable)
798 BOOST_OPERATOR_TEMPLATE(ring_operators)
799 BOOST_OPERATOR_TEMPLATE(ordered_ring_operators)
800 BOOST_OPERATOR_TEMPLATE(field_operators)
801 BOOST_OPERATOR_TEMPLATE(ordered_field_operators)
802 BOOST_OPERATOR_TEMPLATE(euclidian_ring_operators)
803 BOOST_OPERATOR_TEMPLATE(ordered_euclidian_ring_operators)
804 BOOST_OPERATOR_TEMPLATE(euclidean_ring_operators)
805 BOOST_OPERATOR_TEMPLATE(ordered_euclidean_ring_operators)
806 BOOST_OPERATOR_TEMPLATE2(input_iteratable)
807 BOOST_OPERATOR_TEMPLATE1(output_iteratable)
808 BOOST_OPERATOR_TEMPLATE2(forward_iteratable)
809 BOOST_OPERATOR_TEMPLATE2(bidirectional_iteratable)
810 BOOST_OPERATOR_TEMPLATE4(random_access_iteratable)
811 
812 #undef BOOST_OPERATOR_TEMPLATE
813 #undef BOOST_OPERATOR_TEMPLATE4
814 #undef BOOST_OPERATOR_TEMPLATE3
815 #undef BOOST_OPERATOR_TEMPLATE2
816 #undef BOOST_OPERATOR_TEMPLATE1
817 
818 template <class T, class U>
819 struct operators2
820     : totally_ordered2<T,U
821     , integer_arithmetic2<T,U
822     , bitwise2<T,U
823       > > > {};
824 
825 template <class T, class U = T>
826 struct operators : operators2<T, U> {};
827 
828 template <class T> struct operators<T, T>
829     : totally_ordered<T
830     , integer_arithmetic<T
831     , bitwise<T
832     , unit_steppable<T
833       > > > > {};
834 
835 //  Iterator helper classes (contributed by Jeremy Siek) -------------------//
836 //  (Input and output iterator helpers contributed by Daryle Walker) -------//
837 //  (Changed to use combined operator classes by Daryle Walker) ------------//
838 //  (Adapted to C++17 by Daniel Frey) --------------------------------------//
839 template <class Category,
840           class T,
841           class Distance = std::ptrdiff_t,
842           class Pointer = T*,
843           class Reference = T&>
844 struct iterator_helper
845 {
846   typedef Category iterator_category;
847   typedef T value_type;
848   typedef Distance difference_type;
849   typedef Pointer pointer;
850   typedef Reference reference;
851 };
852 
853 template <class T,
854           class V,
855           class D = std::ptrdiff_t,
856           class P = V const *,
857           class R = V const &>
858 struct input_iterator_helper
859   : input_iteratable<T, P
860   , iterator_helper<std::input_iterator_tag, V, D, P, R
861     > > {};
862 
863 template<class T>
864 struct output_iterator_helper
865   : output_iteratable<T
866   , iterator_helper<std::output_iterator_tag, void, void, void, void
867   > >
868 {
operator *boost::operators_impl::output_iterator_helper869   T& operator*()  { return static_cast<T&>(*this); }
operator ++boost::operators_impl::output_iterator_helper870   T& operator++() { return static_cast<T&>(*this); }
871 };
872 
873 template <class T,
874           class V,
875           class D = std::ptrdiff_t,
876           class P = V*,
877           class R = V&>
878 struct forward_iterator_helper
879   : forward_iteratable<T, P
880   , iterator_helper<std::forward_iterator_tag, V, D, P, R
881     > > {};
882 
883 template <class T,
884           class V,
885           class D = std::ptrdiff_t,
886           class P = V*,
887           class R = V&>
888 struct bidirectional_iterator_helper
889   : bidirectional_iteratable<T, P
890   , iterator_helper<std::bidirectional_iterator_tag, V, D, P, R
891     > > {};
892 
893 template <class T,
894           class V,
895           class D = std::ptrdiff_t,
896           class P = V*,
897           class R = V&>
898 struct random_access_iterator_helper
899   : random_access_iteratable<T, P, D, R
900   , iterator_helper<std::random_access_iterator_tag, V, D, P, R
901     > >
902 {
requires_difference_operator(const T & x,const T & y)903   friend D requires_difference_operator(const T& x, const T& y) {
904     return x - y;
905   }
906 }; // random_access_iterator_helper
907 
908 } // namespace operators_impl
909 using namespace operators_impl;
910 
911 } // namespace boost
912 
913 #if defined(__sgi) && !defined(__GNUC__)
914 #pragma reset woff 1234
915 #endif
916 
917 #endif // BOOST_NO_OPERATORS_IN_NAMESPACE
918 #endif // BOOST_OPERATORS_HPP
919