Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/operators.hpp @ 49

Last change on this file since 49 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

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