source: NonGTP/Boost/boost/operators.hpp @ 857

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