1// Boost operators.hpp header file ----------------------------------------//
2
3// (C) Copyright David Abrahams, Jeremy Siek, Daryle Walker 1999-2001.
4// (C) Copyright Daniel Frey 2002-2016.
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// 22 Feb 16 Added ADL protection, preserve old work-arounds in
13// operators_v1.hpp and clean up this file. (Daniel Frey)
14// 16 Dec 10 Limit warning suppression for 4284 to older versions of VC++
15// (Matthew Bradbury, fixes #4432)
16// 07 Aug 08 Added "euclidean" spelling. (Daniel Frey)
17// 03 Apr 08 Make sure "convertible to bool" is sufficient
18// for T::operator<, etc. (Daniel Frey)
19// 24 May 07 Changed empty_base to depend on T, see
20// http://svn.boost.org/trac/boost/ticket/979
21// 21 Oct 02 Modified implementation of operators to allow compilers with a
22// correct named return value optimization (NRVO) to produce optimal
23// code. (Daniel Frey)
24// 02 Dec 01 Bug fixed in random_access_iteratable. (Helmut Zeisel)
25// 28 Sep 01 Factored out iterator operator groups. (Daryle Walker)
26// 27 Aug 01 'left' form for non commutative operators added;
27// additional classes for groups of related operators added;
28// workaround for empty base class optimization
29// bug of GCC 3.0 (Helmut Zeisel)
30// 25 Jun 01 output_iterator_helper changes: removed default template
31// parameters, added support for self-proxying, additional
32// documentation and tests (Aleksey Gurtovoy)
33// 29 May 01 Added operator classes for << and >>. Added input and output
34// iterator helper classes. Added classes to connect equality and
35// relational operators. Added classes for groups of related
36// operators. Reimplemented example operator and iterator helper
37// classes in terms of the new groups. (Daryle Walker, with help
38// from Alexy Gurtovoy)
39// 11 Feb 01 Fixed bugs in the iterator helpers which prevented explicitly
40// supplied arguments from actually being used (Dave Abrahams)
41// 04 Jul 00 Fixed NO_OPERATORS_IN_NAMESPACE bugs, major cleanup and
42// refactoring of compiler workarounds, additional documentation
43// (Alexy Gurtovoy and Mark Rodgers with some help and prompting from
44// Dave Abrahams)
45// 28 Jun 00 General cleanup and integration of bugfixes from Mark Rodgers and
46// Jeremy Siek (Dave Abrahams)
47// 20 Jun 00 Changes to accommodate Borland C++Builder 4 and Borland C++ 5.5
48// (Mark Rodgers)
49// 20 Jun 00 Minor fixes to the prior revision (Aleksey Gurtovoy)
50// 10 Jun 00 Support for the base class chaining technique was added
51// (Aleksey Gurtovoy). See documentation and the comments below
52// for the details.
53// 12 Dec 99 Initial version with iterator operators (Jeremy Siek)
54// 18 Nov 99 Change name "divideable" to "dividable", remove unnecessary
55// specializations of dividable, subtractable, modable (Ed Brey)
56// 17 Nov 99 Add comments (Beman Dawes)
57// Remove unnecessary specialization of operators<> (Ed Brey)
58// 15 Nov 99 Fix less_than_comparable<T,U> second operand type for first two
59// operators.(Beman Dawes)
60// 12 Nov 99 Add operators templates (Ed Brey)
61// 11 Nov 99 Add single template parameter version for compilers without
62// partial specialization (Beman Dawes)
63// 10 Nov 99 Initial version
64
65// 10 Jun 00:
66// An additional optional template parameter was added to most of
67// operator templates to support the base class chaining technique (see
68// documentation for the details). Unfortunately, a straightforward
69// implementation of this change would have broken compatibility with the
70// previous version of the library by making it impossible to use the same
71// template name (e.g. 'addable') for both the 1- and 2-argument versions of
72// an operator template. This implementation solves the backward-compatibility
73// issue at the cost of some simplicity.
74//
75// One of the complications is an existence of special auxiliary class template
76// 'is_chained_base<>' (see 'operators_detail' namespace below), which is used
77// to determine whether its template parameter is a library's operator template
78// or not. You have to specialize 'is_chained_base<>' for each new
79// operator template you add to the library.
80//
81// However, most of the non-trivial implementation details are hidden behind
82// several local macros defined below, and as soon as you understand them,
83// you understand the whole library implementation.
84
85#ifndef BOOST_OPERATORS_HPP
86#define BOOST_OPERATORS_HPP
87
88// If old work-arounds are needed, refer to the preserved version without
89// ADL protection.
90#if defined(BOOST_NO_OPERATORS_IN_NAMESPACE) || defined(BOOST_USE_OPERATORS_V1)
91#include "operators_v1.hpp"
92#else
93
94#include <cstddef>
95#include <iterator>
96
97#include <boost/config.hpp>
98#include <boost/detail/workaround.hpp>
99
100#if defined(__sgi) && !defined(__GNUC__)
101# pragma set woff 1234
102#endif
103
104#if BOOST_WORKAROUND(BOOST_MSVC, < 1600)
105# pragma warning( disable : 4284 ) // complaint about return type of
106#endif // operator-> not begin a UDT
107
108// In this section we supply the xxxx1 and xxxx2 forms of the operator
109// templates, which are explicitly targeted at the 1-type-argument and
110// 2-type-argument operator forms, respectively.
111
112namespace boost
113{
114namespace operators_impl
115{
116namespace operators_detail
117{
118
119template <typename T> class empty_base {};
120
121} // namespace operators_detail
122
123// Basic operator classes (contributed by Dave Abrahams) ------------------//
124
125// Note that friend functions defined in a class are implicitly inline.
126// See the C++ std, 11.4 [class.friend] paragraph 5
127
128template <class T, class U, class B = operators_detail::empty_base<T> >
129struct less_than_comparable2 : B
130{
131 friend bool operator<=(const T& x, const U& y) { return !static_cast<bool>(x > y); }
132 friend bool operator>=(const T& x, const U& y) { return !static_cast<bool>(x < y); }
133 friend bool operator>(const U& x, const T& y) { return y < x; }
134 friend bool operator<(const U& x, const T& y) { return y > x; }
135 friend bool operator<=(const U& x, const T& y) { return !static_cast<bool>(y < x); }
136 friend bool operator>=(const U& x, const T& y) { return !static_cast<bool>(y > x); }
137};
138
139template <class T, class B = operators_detail::empty_base<T> >
140struct less_than_comparable1 : B
141{
142 friend bool operator>(const T& x, const T& y) { return y < x; }
143 friend bool operator<=(const T& x, const T& y) { return !static_cast<bool>(y < x); }
144 friend bool operator>=(const T& x, const T& y) { return !static_cast<bool>(x < y); }
145};
146
147template <class T, class U, class B = operators_detail::empty_base<T> >
148struct equality_comparable2 : B
149{
150 friend bool operator==(const U& y, const T& x) { return x == y; }
151 friend bool operator!=(const U& y, const T& x) { return !static_cast<bool>(x == y); }
152 friend bool operator!=(const T& y, const U& x) { return !static_cast<bool>(y == x); }
153};
154
155template <class T, class B = operators_detail::empty_base<T> >
156struct equality_comparable1 : B
157{
158 friend bool operator!=(const T& x, const T& y) { return !static_cast<bool>(x == y); }
159};
160
161// A macro which produces "name_2left" from "name".
162#define BOOST_OPERATOR2_LEFT(name) name##2##_##left
163
164// NRVO-friendly implementation (contributed by Daniel Frey) ---------------//
165
166#if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
167
168// This is the optimal implementation for ISO/ANSI C++,
169// but it requires the compiler to implement the NRVO.
170// If the compiler has no NRVO, this is the best symmetric
171// implementation available.
172
173#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
174template <class T, class U, class B = operators_detail::empty_base<T> > \
175struct NAME##2 : B \
176{ \
177 friend T operator OP( const T& lhs, const U& rhs ) \
178 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
179 friend T operator OP( const U& lhs, const T& rhs ) \
180 { T nrv( rhs ); nrv OP##= lhs; return nrv; } \
181}; \
182 \
183template <class T, class B = operators_detail::empty_base<T> > \
184struct NAME##1 : B \
185{ \
186 friend T operator OP( const T& lhs, const T& rhs ) \
187 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
188};
189
190#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \
191template <class T, class U, class B = operators_detail::empty_base<T> > \
192struct NAME##2 : B \
193{ \
194 friend T operator OP( const T& lhs, const U& rhs ) \
195 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
196}; \
197 \
198template <class T, class U, class B = operators_detail::empty_base<T> > \
199struct BOOST_OPERATOR2_LEFT(NAME) : B \
200{ \
201 friend T operator OP( const U& lhs, const T& rhs ) \
202 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
203}; \
204 \
205template <class T, class B = operators_detail::empty_base<T> > \
206struct NAME##1 : B \
207{ \
208 friend T operator OP( const T& lhs, const T& rhs ) \
209 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
210};
211
212#else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
213
214// For compilers without NRVO the following code is optimal, but not
215// symmetric! Note that the implementation of
216// BOOST_OPERATOR2_LEFT(NAME) only looks cool, but doesn't provide
217// optimization opportunities to the compiler :)
218
219#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
220template <class T, class U, class B = operators_detail::empty_base<T> > \
221struct NAME##2 : B \
222{ \
223 friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
224 friend T operator OP( const U& lhs, T rhs ) { return rhs OP##= lhs; } \
225}; \
226 \
227template <class T, class B = operators_detail::empty_base<T> > \
228struct NAME##1 : B \
229{ \
230 friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
231};
232
233#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \
234template <class T, class U, class B = operators_detail::empty_base<T> > \
235struct NAME##2 : B \
236{ \
237 friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
238}; \
239 \
240template <class T, class U, class B = operators_detail::empty_base<T> > \
241struct BOOST_OPERATOR2_LEFT(NAME) : B \
242{ \
243 friend T operator OP( const U& lhs, const T& rhs ) \
244 { return T( lhs ) OP##= rhs; } \
245}; \
246 \
247template <class T, class B = operators_detail::empty_base<T> > \
248struct NAME##1 : B \
249{ \
250 friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
251};
252
253#endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
254
255BOOST_BINARY_OPERATOR_COMMUTATIVE( multipliable, * )
256BOOST_BINARY_OPERATOR_COMMUTATIVE( addable, + )
257BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( subtractable, - )
258BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( dividable, / )
259BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( modable, % )
260BOOST_BINARY_OPERATOR_COMMUTATIVE( xorable, ^ )
261BOOST_BINARY_OPERATOR_COMMUTATIVE( andable, & )
262BOOST_BINARY_OPERATOR_COMMUTATIVE( orable, | )
263
264#undef BOOST_BINARY_OPERATOR_COMMUTATIVE
265#undef BOOST_BINARY_OPERATOR_NON_COMMUTATIVE
266#undef BOOST_OPERATOR2_LEFT
267
268// incrementable and decrementable contributed by Jeremy Siek
269
270template <class T, class B = operators_detail::empty_base<T> >
271struct incrementable : B
272{
273 friend T operator++(T& x, int)
274 {
275 incrementable_type nrv(x);
276 ++x;
277 return nrv;
278 }
279private: // The use of this typedef works around a Borland bug
280 typedef T incrementable_type;
281};
282
283template <class T, class B = operators_detail::empty_base<T> >
284struct decrementable : B
285{
286 friend T operator--(T& x, int)
287 {
288 decrementable_type nrv(x);
289 --x;
290 return nrv;
291 }
292private: // The use of this typedef works around a Borland bug
293 typedef T decrementable_type;
294};
295
296// Iterator operator classes (contributed by Jeremy Siek) ------------------//
297
298template <class T, class P, class B = operators_detail::empty_base<T> >
299struct dereferenceable : B
300{
301 P operator->() const
302 {
303 return &*static_cast<const T&>(*this);
304 }
305};
306
307template <class T, class I, class R, class B = operators_detail::empty_base<T> >
308struct indexable : B
309{
310 R operator[](I n) const
311 {
312 return *(static_cast<const T&>(*this) + n);
313 }
314};
315
316// More operator classes (contributed by Daryle Walker) --------------------//
317// (NRVO-friendly implementation contributed by Daniel Frey) ---------------//
318
319#if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
320
321#define BOOST_BINARY_OPERATOR( NAME, OP ) \
322template <class T, class U, class B = operators_detail::empty_base<T> > \
323struct NAME##2 : B \
324{ \
325 friend T operator OP( const T& lhs, const U& rhs ) \
326 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
327}; \
328 \
329template <class T, class B = operators_detail::empty_base<T> > \
330struct NAME##1 : B \
331{ \
332 friend T operator OP( const T& lhs, const T& rhs ) \
333 { T nrv( lhs ); nrv OP##= rhs; return nrv; } \
334};
335
336#else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
337
338#define BOOST_BINARY_OPERATOR( NAME, OP ) \
339template <class T, class U, class B = operators_detail::empty_base<T> > \
340struct NAME##2 : B \
341{ \
342 friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
343}; \
344 \
345template <class T, class B = operators_detail::empty_base<T> > \
346struct NAME##1 : B \
347{ \
348 friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
349};
350
351#endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
352
353BOOST_BINARY_OPERATOR( left_shiftable, << )
354BOOST_BINARY_OPERATOR( right_shiftable, >> )
355
356#undef BOOST_BINARY_OPERATOR
357
358template <class T, class U, class B = operators_detail::empty_base<T> >
359struct equivalent2 : B
360{
361 friend bool operator==(const T& x, const U& y)
362 {
363 return !static_cast<bool>(x < y) && !static_cast<bool>(x > y);
364 }
365};
366
367template <class T, class B = operators_detail::empty_base<T> >
368struct equivalent1 : B
369{
370 friend bool operator==(const T&x, const T&y)
371 {
372 return !static_cast<bool>(x < y) && !static_cast<bool>(y < x);
373 }
374};
375
376template <class T, class U, class B = operators_detail::empty_base<T> >
377struct partially_ordered2 : B
378{
379 friend bool operator<=(const T& x, const U& y)
380 { return static_cast<bool>(x < y) || static_cast<bool>(x == y); }
381 friend bool operator>=(const T& x, const U& y)
382 { return static_cast<bool>(x > y) || static_cast<bool>(x == y); }
383 friend bool operator>(const U& x, const T& y)
384 { return y < x; }
385 friend bool operator<(const U& x, const T& y)
386 { return y > x; }
387 friend bool operator<=(const U& x, const T& y)
388 { return static_cast<bool>(y > x) || static_cast<bool>(y == x); }
389 friend bool operator>=(const U& x, const T& y)
390 { return static_cast<bool>(y < x) || static_cast<bool>(y == x); }
391};
392
393template <class T, class B = operators_detail::empty_base<T> >
394struct partially_ordered1 : B
395{
396 friend bool operator>(const T& x, const T& y)
397 { return y < x; }
398 friend bool operator<=(const T& x, const T& y)
399 { return static_cast<bool>(x < y) || static_cast<bool>(x == y); }
400 friend bool operator>=(const T& x, const T& y)
401 { return static_cast<bool>(y < x) || static_cast<bool>(x == y); }
402};
403
404// Combined operator classes (contributed by Daryle Walker) ----------------//
405
406template <class T, class U, class B = operators_detail::empty_base<T> >
407struct totally_ordered2
408 : less_than_comparable2<T, U
409 , equality_comparable2<T, U, B
410 > > {};
411
412template <class T, class B = operators_detail::empty_base<T> >
413struct totally_ordered1
414 : less_than_comparable1<T
415 , equality_comparable1<T, B
416 > > {};
417
418template <class T, class U, class B = operators_detail::empty_base<T> >
419struct additive2
420 : addable2<T, U
421 , subtractable2<T, U, B
422 > > {};
423
424template <class T, class B = operators_detail::empty_base<T> >
425struct additive1
426 : addable1<T
427 , subtractable1<T, B
428 > > {};
429
430template <class T, class U, class B = operators_detail::empty_base<T> >
431struct multiplicative2
432 : multipliable2<T, U
433 , dividable2<T, U, B
434 > > {};
435
436template <class T, class B = operators_detail::empty_base<T> >
437struct multiplicative1
438 : multipliable1<T
439 , dividable1<T, B
440 > > {};
441
442template <class T, class U, class B = operators_detail::empty_base<T> >
443struct integer_multiplicative2
444 : multiplicative2<T, U
445 , modable2<T, U, B
446 > > {};
447
448template <class T, class B = operators_detail::empty_base<T> >
449struct integer_multiplicative1
450 : multiplicative1<T
451 , modable1<T, B
452 > > {};
453
454template <class T, class U, class B = operators_detail::empty_base<T> >
455struct arithmetic2
456 : additive2<T, U
457 , multiplicative2<T, U, B
458 > > {};
459
460template <class T, class B = operators_detail::empty_base<T> >
461struct arithmetic1
462 : additive1<T
463 , multiplicative1<T, B
464 > > {};
465
466template <class T, class U, class B = operators_detail::empty_base<T> >
467struct integer_arithmetic2
468 : additive2<T, U
469 , integer_multiplicative2<T, U, B
470 > > {};
471
472template <class T, class B = operators_detail::empty_base<T> >
473struct integer_arithmetic1
474 : additive1<T
475 , integer_multiplicative1<T, B
476 > > {};
477
478template <class T, class U, class B = operators_detail::empty_base<T> >
479struct bitwise2
480 : xorable2<T, U
481 , andable2<T, U
482 , orable2<T, U, B
483 > > > {};
484
485template <class T, class B = operators_detail::empty_base<T> >
486struct bitwise1
487 : xorable1<T
488 , andable1<T
489 , orable1<T, B
490 > > > {};
491
492template <class T, class B = operators_detail::empty_base<T> >
493struct unit_steppable
494 : incrementable<T
495 , decrementable<T, B
496 > > {};
497
498template <class T, class U, class B = operators_detail::empty_base<T> >
499struct shiftable2
500 : left_shiftable2<T, U
501 , right_shiftable2<T, U, B
502 > > {};
503
504template <class T, class B = operators_detail::empty_base<T> >
505struct shiftable1
506 : left_shiftable1<T
507 , right_shiftable1<T, B
508 > > {};
509
510template <class T, class U, class B = operators_detail::empty_base<T> >
511struct ring_operators2
512 : additive2<T, U
513 , subtractable2_left<T, U
514 , multipliable2<T, U, B
515 > > > {};
516
517template <class T, class B = operators_detail::empty_base<T> >
518struct ring_operators1
519 : additive1<T
520 , multipliable1<T, B
521 > > {};
522
523template <class T, class U, class B = operators_detail::empty_base<T> >
524struct ordered_ring_operators2
525 : ring_operators2<T, U
526 , totally_ordered2<T, U, B
527 > > {};
528
529template <class T, class B = operators_detail::empty_base<T> >
530struct ordered_ring_operators1
531 : ring_operators1<T
532 , totally_ordered1<T, B
533 > > {};
534
535template <class T, class U, class B = operators_detail::empty_base<T> >
536struct field_operators2
537 : ring_operators2<T, U
538 , dividable2<T, U
539 , dividable2_left<T, U, B
540 > > > {};
541
542template <class T, class B = operators_detail::empty_base<T> >
543struct field_operators1
544 : ring_operators1<T
545 , dividable1<T, B
546 > > {};
547
548template <class T, class U, class B = operators_detail::empty_base<T> >
549struct ordered_field_operators2
550 : field_operators2<T, U
551 , totally_ordered2<T, U, B
552 > > {};
553
554template <class T, class B = operators_detail::empty_base<T> >
555struct ordered_field_operators1
556 : field_operators1<T
557 , totally_ordered1<T, B
558 > > {};
559
560template <class T, class U, class B = operators_detail::empty_base<T> >
561struct euclidian_ring_operators2
562 : ring_operators2<T, U
563 , dividable2<T, U
564 , dividable2_left<T, U
565 , modable2<T, U
566 , modable2_left<T, U, B
567 > > > > > {};
568
569template <class T, class B = operators_detail::empty_base<T> >
570struct euclidian_ring_operators1
571 : ring_operators1<T
572 , dividable1<T
573 , modable1<T, B
574 > > > {};
575
576template <class T, class U, class B = operators_detail::empty_base<T> >
577struct ordered_euclidian_ring_operators2
578 : totally_ordered2<T, U
579 , euclidian_ring_operators2<T, U, B
580 > > {};
581
582template <class T, class B = operators_detail::empty_base<T> >
583struct ordered_euclidian_ring_operators1
584 : totally_ordered1<T
585 , euclidian_ring_operators1<T, B
586 > > {};
587
588template <class T, class U, class B = operators_detail::empty_base<T> >
589struct euclidean_ring_operators2
590 : ring_operators2<T, U
591 , dividable2<T, U
592 , dividable2_left<T, U
593 , modable2<T, U
594 , modable2_left<T, U, B
595 > > > > > {};
596
597template <class T, class B = operators_detail::empty_base<T> >
598struct euclidean_ring_operators1
599 : ring_operators1<T
600 , dividable1<T
601 , modable1<T, B
602 > > > {};
603
604template <class T, class U, class B = operators_detail::empty_base<T> >
605struct ordered_euclidean_ring_operators2
606 : totally_ordered2<T, U
607 , euclidean_ring_operators2<T, U, B
608 > > {};
609
610template <class T, class B = operators_detail::empty_base<T> >
611struct ordered_euclidean_ring_operators1
612 : totally_ordered1<T
613 , euclidean_ring_operators1<T, B
614 > > {};
615
616template <class T, class P, class B = operators_detail::empty_base<T> >
617struct input_iteratable
618 : equality_comparable1<T
619 , incrementable<T
620 , dereferenceable<T, P, B
621 > > > {};
622
623template <class T, class B = operators_detail::empty_base<T> >
624struct output_iteratable
625 : incrementable<T, B
626 > {};
627
628template <class T, class P, class B = operators_detail::empty_base<T> >
629struct forward_iteratable
630 : input_iteratable<T, P, B
631 > {};
632
633template <class T, class P, class B = operators_detail::empty_base<T> >
634struct bidirectional_iteratable
635 : forward_iteratable<T, P
636 , decrementable<T, B
637 > > {};
638
639// To avoid repeated derivation from equality_comparable,
640// which is an indirect base class of bidirectional_iterable,
641// random_access_iteratable must not be derived from totally_ordered1
642// but from less_than_comparable1 only. (Helmut Zeisel, 02-Dec-2001)
643template <class T, class P, class D, class R, class B = operators_detail::empty_base<T> >
644struct random_access_iteratable
645 : bidirectional_iteratable<T, P
646 , less_than_comparable1<T
647 , additive2<T, D
648 , indexable<T, D, R, B
649 > > > > {};
650
651
652//
653// Here's where we put it all together, defining the xxxx forms of the templates.
654// We also define specializations of is_chained_base<> for
655// the xxxx, xxxx1, and xxxx2 templates.
656//
657
658namespace operators_detail
659{
660
661// A type parameter is used instead of a plain bool because Borland's compiler
662// didn't cope well with the more obvious non-type template parameter.
663struct true_t {};
664struct false_t {};
665
666} // namespace operators_detail
667
668// is_chained_base<> - a traits class used to distinguish whether an operator
669// template argument is being used for base class chaining, or is specifying a
670// 2nd argument type.
671
672// Unspecialized version assumes that most types are not being used for base
673// class chaining. We specialize for the operator templates defined in this
674// library.
675template<class T> struct is_chained_base {
676 typedef operators_detail::false_t value;
677};
678
679// Provide a specialization of 'is_chained_base<>'
680// for a 4-type-argument operator template.
681# define BOOST_OPERATOR_TEMPLATE4(template_name4) \
682 template<class T, class U, class V, class W, class B> \
683 struct is_chained_base< template_name4<T, U, V, W, B> > { \
684 typedef operators_detail::true_t value; \
685 };
686
687// Provide a specialization of 'is_chained_base<>'
688// for a 3-type-argument operator template.
689# define BOOST_OPERATOR_TEMPLATE3(template_name3) \
690 template<class T, class U, class V, class B> \
691 struct is_chained_base< template_name3<T, U, V, B> > { \
692 typedef operators_detail::true_t value; \
693 };
694
695// Provide a specialization of 'is_chained_base<>'
696// for a 2-type-argument operator template.
697# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
698 template<class T, class U, class B> \
699 struct is_chained_base< template_name2<T, U, B> > { \
700 typedef operators_detail::true_t value; \
701 };
702
703// Provide a specialization of 'is_chained_base<>'
704// for a 1-type-argument operator template.
705# define BOOST_OPERATOR_TEMPLATE1(template_name1) \
706 template<class T, class B> \
707 struct is_chained_base< template_name1<T, B> > { \
708 typedef operators_detail::true_t value; \
709 };
710
711// BOOST_OPERATOR_TEMPLATE(template_name) defines template_name<> such that it
712// can be used for specifying both 1-argument and 2-argument forms. Requires the
713// existence of two previously defined class templates named '<template_name>1'
714// and '<template_name>2' which must implement the corresponding 1- and 2-
715// argument forms.
716//
717// The template type parameter O == is_chained_base<U>::value is used to
718// distinguish whether the 2nd argument to <template_name> is being used for
719// base class chaining from another boost operator template or is describing a
720// 2nd operand type. O == true_t only when U is actually an another operator
721// template from the library. Partial specialization is used to select an
722// implementation in terms of either '<template_name>1' or '<template_name>2'.
723//
724
725# define BOOST_OPERATOR_TEMPLATE(template_name) \
726template <class T \
727 ,class U = T \
728 ,class B = operators_detail::empty_base<T> \
729 ,class O = typename is_chained_base<U>::value \
730 > \
731struct template_name; \
732 \
733template<class T, class U, class B> \
734struct template_name<T, U, B, operators_detail::false_t> \
735 : template_name##2<T, U, B> {}; \
736 \
737template<class T, class U> \
738struct template_name<T, U, operators_detail::empty_base<T>, operators_detail::true_t> \
739 : template_name##1<T, U> {}; \
740 \
741template <class T, class B> \
742struct template_name<T, T, B, operators_detail::false_t> \
743 : template_name##1<T, B> {}; \
744 \
745template<class T, class U, class B, class O> \
746struct is_chained_base< template_name<T, U, B, O> > { \
747 typedef operators_detail::true_t value; \
748}; \
749 \
750BOOST_OPERATOR_TEMPLATE2(template_name##2) \
751BOOST_OPERATOR_TEMPLATE1(template_name##1)
752
753BOOST_OPERATOR_TEMPLATE(less_than_comparable)
754BOOST_OPERATOR_TEMPLATE(equality_comparable)
755BOOST_OPERATOR_TEMPLATE(multipliable)
756BOOST_OPERATOR_TEMPLATE(addable)
757BOOST_OPERATOR_TEMPLATE(subtractable)
758BOOST_OPERATOR_TEMPLATE2(subtractable2_left)
759BOOST_OPERATOR_TEMPLATE(dividable)
760BOOST_OPERATOR_TEMPLATE2(dividable2_left)
761BOOST_OPERATOR_TEMPLATE(modable)
762BOOST_OPERATOR_TEMPLATE2(modable2_left)
763BOOST_OPERATOR_TEMPLATE(xorable)
764BOOST_OPERATOR_TEMPLATE(andable)
765BOOST_OPERATOR_TEMPLATE(orable)
766
767BOOST_OPERATOR_TEMPLATE1(incrementable)
768BOOST_OPERATOR_TEMPLATE1(decrementable)
769
770BOOST_OPERATOR_TEMPLATE2(dereferenceable)
771BOOST_OPERATOR_TEMPLATE3(indexable)
772
773BOOST_OPERATOR_TEMPLATE(left_shiftable)
774BOOST_OPERATOR_TEMPLATE(right_shiftable)
775BOOST_OPERATOR_TEMPLATE(equivalent)
776BOOST_OPERATOR_TEMPLATE(partially_ordered)
777
778BOOST_OPERATOR_TEMPLATE(totally_ordered)
779BOOST_OPERATOR_TEMPLATE(additive)
780BOOST_OPERATOR_TEMPLATE(multiplicative)
781BOOST_OPERATOR_TEMPLATE(integer_multiplicative)
782BOOST_OPERATOR_TEMPLATE(arithmetic)
783BOOST_OPERATOR_TEMPLATE(integer_arithmetic)
784BOOST_OPERATOR_TEMPLATE(bitwise)
785BOOST_OPERATOR_TEMPLATE1(unit_steppable)
786BOOST_OPERATOR_TEMPLATE(shiftable)
787BOOST_OPERATOR_TEMPLATE(ring_operators)
788BOOST_OPERATOR_TEMPLATE(ordered_ring_operators)
789BOOST_OPERATOR_TEMPLATE(field_operators)
790BOOST_OPERATOR_TEMPLATE(ordered_field_operators)
791BOOST_OPERATOR_TEMPLATE(euclidian_ring_operators)
792BOOST_OPERATOR_TEMPLATE(ordered_euclidian_ring_operators)
793BOOST_OPERATOR_TEMPLATE(euclidean_ring_operators)
794BOOST_OPERATOR_TEMPLATE(ordered_euclidean_ring_operators)
795BOOST_OPERATOR_TEMPLATE2(input_iteratable)
796BOOST_OPERATOR_TEMPLATE1(output_iteratable)
797BOOST_OPERATOR_TEMPLATE2(forward_iteratable)
798BOOST_OPERATOR_TEMPLATE2(bidirectional_iteratable)
799BOOST_OPERATOR_TEMPLATE4(random_access_iteratable)
800
801#undef BOOST_OPERATOR_TEMPLATE
802#undef BOOST_OPERATOR_TEMPLATE4
803#undef BOOST_OPERATOR_TEMPLATE3
804#undef BOOST_OPERATOR_TEMPLATE2
805#undef BOOST_OPERATOR_TEMPLATE1
806
807template <class T, class U>
808struct operators2
809 : totally_ordered2<T,U
810 , integer_arithmetic2<T,U
811 , bitwise2<T,U
812 > > > {};
813
814template <class T, class U = T>
815struct operators : operators2<T, U> {};
816
817template <class T> struct operators<T, T>
818 : totally_ordered<T
819 , integer_arithmetic<T
820 , bitwise<T
821 , unit_steppable<T
822 > > > > {};
823
824// Iterator helper classes (contributed by Jeremy Siek) -------------------//
825// (Input and output iterator helpers contributed by Daryle Walker) -------//
826// (Changed to use combined operator classes by Daryle Walker) ------------//
827template <class T,
828 class V,
829 class D = std::ptrdiff_t,
830 class P = V const *,
831 class R = V const &>
832struct input_iterator_helper
833 : input_iteratable<T, P
834 , std::iterator<std::input_iterator_tag, V, D, P, R
835 > > {};
836
837template<class T>
838struct output_iterator_helper
839 : output_iteratable<T
840 , std::iterator<std::output_iterator_tag, void, void, void, void
841 > >
842{
843 T& operator*() { return static_cast<T&>(*this); }
844 T& operator++() { return static_cast<T&>(*this); }
845};
846
847template <class T,
848 class V,
849 class D = std::ptrdiff_t,
850 class P = V*,
851 class R = V&>
852struct forward_iterator_helper
853 : forward_iteratable<T, P
854 , std::iterator<std::forward_iterator_tag, V, D, P, R
855 > > {};
856
857template <class T,
858 class V,
859 class D = std::ptrdiff_t,
860 class P = V*,
861 class R = V&>
862struct bidirectional_iterator_helper
863 : bidirectional_iteratable<T, P
864 , std::iterator<std::bidirectional_iterator_tag, V, D, P, R
865 > > {};
866
867template <class T,
868 class V,
869 class D = std::ptrdiff_t,
870 class P = V*,
871 class R = V&>
872struct random_access_iterator_helper
873 : random_access_iteratable<T, P, D, R
874 , std::iterator<std::random_access_iterator_tag, V, D, P, R
875 > >
876{
877 friend D requires_difference_operator(const T& x, const T& y) {
878 return x - y;
879 }
880}; // random_access_iterator_helper
881
882} // namespace operators_impl
883using namespace operators_impl;
884
885} // namespace boost
886
887#if defined(__sgi) && !defined(__GNUC__)
888#pragma reset woff 1234
889#endif
890
891#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
892#endif // BOOST_OPERATORS_HPP
893