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