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