blob: 156571c1a932ab3bfeb441e8a80d598ec8eecfed [file] [log] [blame]
Brian Silverman60e3e2a2018-08-04 23:57:12 -07001// 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
116namespace boost
117{
118namespace operators_impl
119{
120namespace operators_detail
121{
122
123template <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
132template <class T, class U, class B = operators_detail::empty_base<T> >
133struct less_than_comparable2 : B
134{
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); }
141};
142
143template <class T, class B = operators_detail::empty_base<T> >
144struct less_than_comparable1 : B
145{
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); }
149};
150
151template <class T, class U, class B = operators_detail::empty_base<T> >
152struct equality_comparable2 : B
153{
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); }
157};
158
159template <class T, class B = operators_detail::empty_base<T> >
160struct equality_comparable1 : B
161{
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 ) \
178template <class T, class U, class B = operators_detail::empty_base<T> > \
179struct 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 \
187template <class T, class B = operators_detail::empty_base<T> > \
188struct 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 ) \
195template <class T, class U, class B = operators_detail::empty_base<T> > \
196struct 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 \
202template <class T, class U, class B = operators_detail::empty_base<T> > \
203struct 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 \
209template <class T, class B = operators_detail::empty_base<T> > \
210struct 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 ) \
224template <class T, class U, class B = operators_detail::empty_base<T> > \
225struct 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 \
231template <class T, class B = operators_detail::empty_base<T> > \
232struct 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 ) \
238template <class T, class U, class B = operators_detail::empty_base<T> > \
239struct NAME##2 : B \
240{ \
241 friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
242}; \
243 \
244template <class T, class U, class B = operators_detail::empty_base<T> > \
245struct 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 \
251template <class T, class B = operators_detail::empty_base<T> > \
252struct 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
259BOOST_BINARY_OPERATOR_COMMUTATIVE( multipliable, * )
260BOOST_BINARY_OPERATOR_COMMUTATIVE( addable, + )
261BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( subtractable, - )
262BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( dividable, / )
263BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( modable, % )
264BOOST_BINARY_OPERATOR_COMMUTATIVE( xorable, ^ )
265BOOST_BINARY_OPERATOR_COMMUTATIVE( andable, & )
266BOOST_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
274template <class T, class B = operators_detail::empty_base<T> >
275struct incrementable : B
276{
277 friend T operator++(T& x, int)
278 {
279 incrementable_type nrv(x);
280 ++x;
281 return nrv;
282 }
283private: // The use of this typedef works around a Borland bug
284 typedef T incrementable_type;
285};
286
287template <class T, class B = operators_detail::empty_base<T> >
288struct decrementable : B
289{
290 friend T operator--(T& x, int)
291 {
292 decrementable_type nrv(x);
293 --x;
294 return nrv;
295 }
296private: // 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
302template <class T, class P, class B = operators_detail::empty_base<T> >
303struct dereferenceable : B
304{
305 P operator->() const
306 {
307 return ::boost::addressof(*static_cast<const T&>(*this));
308 }
309};
310
311template <class T, class I, class R, class B = operators_detail::empty_base<T> >
312struct indexable : B
313{
314 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 ) \
326template <class T, class U, class B = operators_detail::empty_base<T> > \
327struct 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 \
333template <class T, class B = operators_detail::empty_base<T> > \
334struct 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 ) \
343template <class T, class U, class B = operators_detail::empty_base<T> > \
344struct NAME##2 : B \
345{ \
346 friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
347}; \
348 \
349template <class T, class B = operators_detail::empty_base<T> > \
350struct 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
357BOOST_BINARY_OPERATOR( left_shiftable, << )
358BOOST_BINARY_OPERATOR( right_shiftable, >> )
359
360#undef BOOST_BINARY_OPERATOR
361
362template <class T, class U, class B = operators_detail::empty_base<T> >
363struct equivalent2 : B
364{
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
371template <class T, class B = operators_detail::empty_base<T> >
372struct equivalent1 : B
373{
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
380template <class T, class U, class B = operators_detail::empty_base<T> >
381struct partially_ordered2 : B
382{
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)
388 { return y < x; }
389 friend bool operator<(const U& x, const T& y)
390 { return y > x; }
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); }
395};
396
397template <class T, class B = operators_detail::empty_base<T> >
398struct partially_ordered1 : B
399{
400 friend bool operator>(const T& x, const T& y)
401 { return y < x; }
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); }
406};
407
408// Combined operator classes (contributed by Daryle Walker) ----------------//
409
410template <class T, class U, class B = operators_detail::empty_base<T> >
411struct totally_ordered2
412 : less_than_comparable2<T, U
413 , equality_comparable2<T, U, B
414 > > {};
415
416template <class T, class B = operators_detail::empty_base<T> >
417struct totally_ordered1
418 : less_than_comparable1<T
419 , equality_comparable1<T, B
420 > > {};
421
422template <class T, class U, class B = operators_detail::empty_base<T> >
423struct additive2
424 : addable2<T, U
425 , subtractable2<T, U, B
426 > > {};
427
428template <class T, class B = operators_detail::empty_base<T> >
429struct additive1
430 : addable1<T
431 , subtractable1<T, B
432 > > {};
433
434template <class T, class U, class B = operators_detail::empty_base<T> >
435struct multiplicative2
436 : multipliable2<T, U
437 , dividable2<T, U, B
438 > > {};
439
440template <class T, class B = operators_detail::empty_base<T> >
441struct multiplicative1
442 : multipliable1<T
443 , dividable1<T, B
444 > > {};
445
446template <class T, class U, class B = operators_detail::empty_base<T> >
447struct integer_multiplicative2
448 : multiplicative2<T, U
449 , modable2<T, U, B
450 > > {};
451
452template <class T, class B = operators_detail::empty_base<T> >
453struct integer_multiplicative1
454 : multiplicative1<T
455 , modable1<T, B
456 > > {};
457
458template <class T, class U, class B = operators_detail::empty_base<T> >
459struct arithmetic2
460 : additive2<T, U
461 , multiplicative2<T, U, B
462 > > {};
463
464template <class T, class B = operators_detail::empty_base<T> >
465struct arithmetic1
466 : additive1<T
467 , multiplicative1<T, B
468 > > {};
469
470template <class T, class U, class B = operators_detail::empty_base<T> >
471struct integer_arithmetic2
472 : additive2<T, U
473 , integer_multiplicative2<T, U, B
474 > > {};
475
476template <class T, class B = operators_detail::empty_base<T> >
477struct integer_arithmetic1
478 : additive1<T
479 , integer_multiplicative1<T, B
480 > > {};
481
482template <class T, class U, class B = operators_detail::empty_base<T> >
483struct bitwise2
484 : xorable2<T, U
485 , andable2<T, U
486 , orable2<T, U, B
487 > > > {};
488
489template <class T, class B = operators_detail::empty_base<T> >
490struct bitwise1
491 : xorable1<T
492 , andable1<T
493 , orable1<T, B
494 > > > {};
495
496template <class T, class B = operators_detail::empty_base<T> >
497struct unit_steppable
498 : incrementable<T
499 , decrementable<T, B
500 > > {};
501
502template <class T, class U, class B = operators_detail::empty_base<T> >
503struct shiftable2
504 : left_shiftable2<T, U
505 , right_shiftable2<T, U, B
506 > > {};
507
508template <class T, class B = operators_detail::empty_base<T> >
509struct shiftable1
510 : left_shiftable1<T
511 , right_shiftable1<T, B
512 > > {};
513
514template <class T, class U, class B = operators_detail::empty_base<T> >
515struct ring_operators2
516 : additive2<T, U
517 , subtractable2_left<T, U
518 , multipliable2<T, U, B
519 > > > {};
520
521template <class T, class B = operators_detail::empty_base<T> >
522struct ring_operators1
523 : additive1<T
524 , multipliable1<T, B
525 > > {};
526
527template <class T, class U, class B = operators_detail::empty_base<T> >
528struct ordered_ring_operators2
529 : ring_operators2<T, U
530 , totally_ordered2<T, U, B
531 > > {};
532
533template <class T, class B = operators_detail::empty_base<T> >
534struct ordered_ring_operators1
535 : ring_operators1<T
536 , totally_ordered1<T, B
537 > > {};
538
539template <class T, class U, class B = operators_detail::empty_base<T> >
540struct field_operators2
541 : ring_operators2<T, U
542 , dividable2<T, U
543 , dividable2_left<T, U, B
544 > > > {};
545
546template <class T, class B = operators_detail::empty_base<T> >
547struct field_operators1
548 : ring_operators1<T
549 , dividable1<T, B
550 > > {};
551
552template <class T, class U, class B = operators_detail::empty_base<T> >
553struct ordered_field_operators2
554 : field_operators2<T, U
555 , totally_ordered2<T, U, B
556 > > {};
557
558template <class T, class B = operators_detail::empty_base<T> >
559struct ordered_field_operators1
560 : field_operators1<T
561 , totally_ordered1<T, B
562 > > {};
563
564template <class T, class U, class B = operators_detail::empty_base<T> >
565struct 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
573template <class T, class B = operators_detail::empty_base<T> >
574struct euclidian_ring_operators1
575 : ring_operators1<T
576 , dividable1<T
577 , modable1<T, B
578 > > > {};
579
580template <class T, class U, class B = operators_detail::empty_base<T> >
581struct ordered_euclidian_ring_operators2
582 : totally_ordered2<T, U
583 , euclidian_ring_operators2<T, U, B
584 > > {};
585
586template <class T, class B = operators_detail::empty_base<T> >
587struct ordered_euclidian_ring_operators1
588 : totally_ordered1<T
589 , euclidian_ring_operators1<T, B
590 > > {};
591
592template <class T, class U, class B = operators_detail::empty_base<T> >
593struct 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
601template <class T, class B = operators_detail::empty_base<T> >
602struct euclidean_ring_operators1
603 : ring_operators1<T
604 , dividable1<T
605 , modable1<T, B
606 > > > {};
607
608template <class T, class U, class B = operators_detail::empty_base<T> >
609struct ordered_euclidean_ring_operators2
610 : totally_ordered2<T, U
611 , euclidean_ring_operators2<T, U, B
612 > > {};
613
614template <class T, class B = operators_detail::empty_base<T> >
615struct ordered_euclidean_ring_operators1
616 : totally_ordered1<T
617 , euclidean_ring_operators1<T, B
618 > > {};
619
620template <class T, class P, class B = operators_detail::empty_base<T> >
621struct input_iteratable
622 : equality_comparable1<T
623 , incrementable<T
624 , dereferenceable<T, P, B
625 > > > {};
626
627template <class T, class B = operators_detail::empty_base<T> >
628struct output_iteratable
629 : incrementable<T, B
630 > {};
631
632template <class T, class P, class B = operators_detail::empty_base<T> >
633struct forward_iteratable
634 : input_iteratable<T, P, B
635 > {};
636
637template <class T, class P, class B = operators_detail::empty_base<T> >
638struct 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)
647template <class T, class P, class D, class R, class B = operators_detail::empty_base<T> >
648struct 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
662namespace 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.
667struct true_t {};
668struct 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.
679template<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) \
730template <class T \
731 ,class U = T \
732 ,class B = operators_detail::empty_base<T> \
733 ,class O = typename is_chained_base<U>::value \
734 > \
735struct template_name; \
736 \
737template<class T, class U, class B> \
738struct template_name<T, U, B, operators_detail::false_t> \
739 : template_name##2<T, U, B> {}; \
740 \
741template<class T, class U> \
742struct template_name<T, U, operators_detail::empty_base<T>, operators_detail::true_t> \
743 : template_name##1<T, U> {}; \
744 \
745template <class T, class B> \
746struct template_name<T, T, B, operators_detail::false_t> \
747 : template_name##1<T, B> {}; \
748 \
749template<class T, class U, class B, class O> \
750struct is_chained_base< template_name<T, U, B, O> > { \
751 typedef operators_detail::true_t value; \
752}; \
753 \
754BOOST_OPERATOR_TEMPLATE2(template_name##2) \
755BOOST_OPERATOR_TEMPLATE1(template_name##1)
756
757BOOST_OPERATOR_TEMPLATE(less_than_comparable)
758BOOST_OPERATOR_TEMPLATE(equality_comparable)
759BOOST_OPERATOR_TEMPLATE(multipliable)
760BOOST_OPERATOR_TEMPLATE(addable)
761BOOST_OPERATOR_TEMPLATE(subtractable)
762BOOST_OPERATOR_TEMPLATE2(subtractable2_left)
763BOOST_OPERATOR_TEMPLATE(dividable)
764BOOST_OPERATOR_TEMPLATE2(dividable2_left)
765BOOST_OPERATOR_TEMPLATE(modable)
766BOOST_OPERATOR_TEMPLATE2(modable2_left)
767BOOST_OPERATOR_TEMPLATE(xorable)
768BOOST_OPERATOR_TEMPLATE(andable)
769BOOST_OPERATOR_TEMPLATE(orable)
770
771BOOST_OPERATOR_TEMPLATE1(incrementable)
772BOOST_OPERATOR_TEMPLATE1(decrementable)
773
774BOOST_OPERATOR_TEMPLATE2(dereferenceable)
775BOOST_OPERATOR_TEMPLATE3(indexable)
776
777BOOST_OPERATOR_TEMPLATE(left_shiftable)
778BOOST_OPERATOR_TEMPLATE(right_shiftable)
779BOOST_OPERATOR_TEMPLATE(equivalent)
780BOOST_OPERATOR_TEMPLATE(partially_ordered)
781
782BOOST_OPERATOR_TEMPLATE(totally_ordered)
783BOOST_OPERATOR_TEMPLATE(additive)
784BOOST_OPERATOR_TEMPLATE(multiplicative)
785BOOST_OPERATOR_TEMPLATE(integer_multiplicative)
786BOOST_OPERATOR_TEMPLATE(arithmetic)
787BOOST_OPERATOR_TEMPLATE(integer_arithmetic)
788BOOST_OPERATOR_TEMPLATE(bitwise)
789BOOST_OPERATOR_TEMPLATE1(unit_steppable)
790BOOST_OPERATOR_TEMPLATE(shiftable)
791BOOST_OPERATOR_TEMPLATE(ring_operators)
792BOOST_OPERATOR_TEMPLATE(ordered_ring_operators)
793BOOST_OPERATOR_TEMPLATE(field_operators)
794BOOST_OPERATOR_TEMPLATE(ordered_field_operators)
795BOOST_OPERATOR_TEMPLATE(euclidian_ring_operators)
796BOOST_OPERATOR_TEMPLATE(ordered_euclidian_ring_operators)
797BOOST_OPERATOR_TEMPLATE(euclidean_ring_operators)
798BOOST_OPERATOR_TEMPLATE(ordered_euclidean_ring_operators)
799BOOST_OPERATOR_TEMPLATE2(input_iteratable)
800BOOST_OPERATOR_TEMPLATE1(output_iteratable)
801BOOST_OPERATOR_TEMPLATE2(forward_iteratable)
802BOOST_OPERATOR_TEMPLATE2(bidirectional_iteratable)
803BOOST_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
811template <class T, class U>
812struct operators2
813 : totally_ordered2<T,U
814 , integer_arithmetic2<T,U
815 , bitwise2<T,U
816 > > > {};
817
818template <class T, class U = T>
819struct operators : operators2<T, U> {};
820
821template <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) --------------------------------------//
832template <class Category,
833 class T,
834 class Distance = std::ptrdiff_t,
835 class Pointer = T*,
836 class Reference = T&>
837struct 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
846template <class T,
847 class V,
848 class D = std::ptrdiff_t,
849 class P = V const *,
850 class R = V const &>
851struct input_iterator_helper
852 : input_iteratable<T, P
853 , iterator_helper<std::input_iterator_tag, V, D, P, R
854 > > {};
855
856template<class T>
857struct output_iterator_helper
858 : output_iteratable<T
859 , iterator_helper<std::output_iterator_tag, void, void, void, void
860 > >
861{
862 T& operator*() { return static_cast<T&>(*this); }
863 T& operator++() { return static_cast<T&>(*this); }
864};
865
866template <class T,
867 class V,
868 class D = std::ptrdiff_t,
869 class P = V*,
870 class R = V&>
871struct forward_iterator_helper
872 : forward_iteratable<T, P
873 , iterator_helper<std::forward_iterator_tag, V, D, P, R
874 > > {};
875
876template <class T,
877 class V,
878 class D = std::ptrdiff_t,
879 class P = V*,
880 class R = V&>
881struct bidirectional_iterator_helper
882 : bidirectional_iteratable<T, P
883 , iterator_helper<std::bidirectional_iterator_tag, V, D, P, R
884 > > {};
885
886template <class T,
887 class V,
888 class D = std::ptrdiff_t,
889 class P = V*,
890 class R = V&>
891struct 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{
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
902using 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