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