|
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 |
|
92 namespace boost { |
|
93 namespace detail { |
|
94 |
|
95 template <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 |
|
115 namespace 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 |
|
124 template <class T, class U, class B = ::boost::detail::empty_base<T> > |
|
125 struct 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 |
|
135 template <class T, class B = ::boost::detail::empty_base<T> > |
|
136 struct 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 |
|
143 template <class T, class U, class B = ::boost::detail::empty_base<T> > |
|
144 struct 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 |
|
151 template <class T, class B = ::boost::detail::empty_base<T> > |
|
152 struct 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 ) \ |
|
170 template <class T, class U, class B = ::boost::detail::empty_base<T> > \ |
|
171 struct 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 \ |
|
179 template <class T, class B = ::boost::detail::empty_base<T> > \ |
|
180 struct 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 ) \ |
|
187 template <class T, class U, class B = ::boost::detail::empty_base<T> > \ |
|
188 struct 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 \ |
|
194 template <class T, class U, class B = ::boost::detail::empty_base<T> > \ |
|
195 struct 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 \ |
|
201 template <class T, class B = ::boost::detail::empty_base<T> > \ |
|
202 struct 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 ) \ |
|
216 template <class T, class U, class B = ::boost::detail::empty_base<T> > \ |
|
217 struct 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 \ |
|
223 template <class T, class B = ::boost::detail::empty_base<T> > \ |
|
224 struct 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 ) \ |
|
230 template <class T, class U, class B = ::boost::detail::empty_base<T> > \ |
|
231 struct NAME##2 : B \ |
|
232 { \ |
|
233 friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \ |
|
234 }; \ |
|
235 \ |
|
236 template <class T, class U, class B = ::boost::detail::empty_base<T> > \ |
|
237 struct 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 \ |
|
243 template <class T, class B = ::boost::detail::empty_base<T> > \ |
|
244 struct 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 |
|
251 BOOST_BINARY_OPERATOR_COMMUTATIVE( multipliable, * ) |
|
252 BOOST_BINARY_OPERATOR_COMMUTATIVE( addable, + ) |
|
253 BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( subtractable, - ) |
|
254 BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( dividable, / ) |
|
255 BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( modable, % ) |
|
256 BOOST_BINARY_OPERATOR_COMMUTATIVE( xorable, ^ ) |
|
257 BOOST_BINARY_OPERATOR_COMMUTATIVE( andable, & ) |
|
258 BOOST_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 |
|
266 template <class T, class B = ::boost::detail::empty_base<T> > |
|
267 struct incrementable : B |
|
268 { |
|
269 friend T operator++(T& x, int) |
|
270 { |
|
271 incrementable_type nrv(x); |
|
272 ++x; |
|
273 return nrv; |
|
274 } |
|
275 private: // The use of this typedef works around a Borland bug |
|
276 typedef T incrementable_type; |
|
277 }; |
|
278 |
|
279 template <class T, class B = ::boost::detail::empty_base<T> > |
|
280 struct decrementable : B |
|
281 { |
|
282 friend T operator--(T& x, int) |
|
283 { |
|
284 decrementable_type nrv(x); |
|
285 --x; |
|
286 return nrv; |
|
287 } |
|
288 private: // 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 |
|
294 template <class T, class P, class B = ::boost::detail::empty_base<T> > |
|
295 struct dereferenceable : B |
|
296 { |
|
297 P operator->() const |
|
298 { |
|
299 return &*static_cast<const T&>(*this); |
|
300 } |
|
301 }; |
|
302 |
|
303 template <class T, class I, class R, class B = ::boost::detail::empty_base<T> > |
|
304 struct 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 ) \ |
|
318 template <class T, class U, class B = ::boost::detail::empty_base<T> > \ |
|
319 struct 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 \ |
|
325 template <class T, class B = ::boost::detail::empty_base<T> > \ |
|
326 struct 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 ) \ |
|
335 template <class T, class U, class B = ::boost::detail::empty_base<T> > \ |
|
336 struct NAME##2 : B \ |
|
337 { \ |
|
338 friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \ |
|
339 }; \ |
|
340 \ |
|
341 template <class T, class B = ::boost::detail::empty_base<T> > \ |
|
342 struct 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 |
|
349 BOOST_BINARY_OPERATOR( left_shiftable, << ) |
|
350 BOOST_BINARY_OPERATOR( right_shiftable, >> ) |
|
351 |
|
352 #undef BOOST_BINARY_OPERATOR |
|
353 |
|
354 template <class T, class U, class B = ::boost::detail::empty_base<T> > |
|
355 struct equivalent2 : B |
|
356 { |
|
357 friend bool operator==(const T& x, const U& y) |
|
358 { |
|
359 return !(x < y) && !(x > y); |
|
360 } |
|
361 }; |
|
362 |
|
363 template <class T, class B = ::boost::detail::empty_base<T> > |
|
364 struct equivalent1 : B |
|
365 { |
|
366 friend bool operator==(const T&x, const T&y) |
|
367 { |
|
368 return !(x < y) && !(y < x); |
|
369 } |
|
370 }; |
|
371 |
|
372 template <class T, class U, class B = ::boost::detail::empty_base<T> > |
|
373 struct 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 |
|
389 template <class T, class B = ::boost::detail::empty_base<T> > |
|
390 struct 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 |
|
402 template <class T, class U, class B = ::boost::detail::empty_base<T> > |
|
403 struct totally_ordered2 |
|
404 : less_than_comparable2<T, U |
|
405 , equality_comparable2<T, U, B |
|
406 > > {}; |
|
407 |
|
408 template <class T, class B = ::boost::detail::empty_base<T> > |
|
409 struct totally_ordered1 |
|
410 : less_than_comparable1<T |
|
411 , equality_comparable1<T, B |
|
412 > > {}; |
|
413 |
|
414 template <class T, class U, class B = ::boost::detail::empty_base<T> > |
|
415 struct additive2 |
|
416 : addable2<T, U |
|
417 , subtractable2<T, U, B |
|
418 > > {}; |
|
419 |
|
420 template <class T, class B = ::boost::detail::empty_base<T> > |
|
421 struct additive1 |
|
422 : addable1<T |
|
423 , subtractable1<T, B |
|
424 > > {}; |
|
425 |
|
426 template <class T, class U, class B = ::boost::detail::empty_base<T> > |
|
427 struct multiplicative2 |
|
428 : multipliable2<T, U |
|
429 , dividable2<T, U, B |
|
430 > > {}; |
|
431 |
|
432 template <class T, class B = ::boost::detail::empty_base<T> > |
|
433 struct multiplicative1 |
|
434 : multipliable1<T |
|
435 , dividable1<T, B |
|
436 > > {}; |
|
437 |
|
438 template <class T, class U, class B = ::boost::detail::empty_base<T> > |
|
439 struct integer_multiplicative2 |
|
440 : multiplicative2<T, U |
|
441 , modable2<T, U, B |
|
442 > > {}; |
|
443 |
|
444 template <class T, class B = ::boost::detail::empty_base<T> > |
|
445 struct integer_multiplicative1 |
|
446 : multiplicative1<T |
|
447 , modable1<T, B |
|
448 > > {}; |
|
449 |
|
450 template <class T, class U, class B = ::boost::detail::empty_base<T> > |
|
451 struct arithmetic2 |
|
452 : additive2<T, U |
|
453 , multiplicative2<T, U, B |
|
454 > > {}; |
|
455 |
|
456 template <class T, class B = ::boost::detail::empty_base<T> > |
|
457 struct arithmetic1 |
|
458 : additive1<T |
|
459 , multiplicative1<T, B |
|
460 > > {}; |
|
461 |
|
462 template <class T, class U, class B = ::boost::detail::empty_base<T> > |
|
463 struct integer_arithmetic2 |
|
464 : additive2<T, U |
|
465 , integer_multiplicative2<T, U, B |
|
466 > > {}; |
|
467 |
|
468 template <class T, class B = ::boost::detail::empty_base<T> > |
|
469 struct integer_arithmetic1 |
|
470 : additive1<T |
|
471 , integer_multiplicative1<T, B |
|
472 > > {}; |
|
473 |
|
474 template <class T, class U, class B = ::boost::detail::empty_base<T> > |
|
475 struct bitwise2 |
|
476 : xorable2<T, U |
|
477 , andable2<T, U |
|
478 , orable2<T, U, B |
|
479 > > > {}; |
|
480 |
|
481 template <class T, class B = ::boost::detail::empty_base<T> > |
|
482 struct bitwise1 |
|
483 : xorable1<T |
|
484 , andable1<T |
|
485 , orable1<T, B |
|
486 > > > {}; |
|
487 |
|
488 template <class T, class B = ::boost::detail::empty_base<T> > |
|
489 struct unit_steppable |
|
490 : incrementable<T |
|
491 , decrementable<T, B |
|
492 > > {}; |
|
493 |
|
494 template <class T, class U, class B = ::boost::detail::empty_base<T> > |
|
495 struct shiftable2 |
|
496 : left_shiftable2<T, U |
|
497 , right_shiftable2<T, U, B |
|
498 > > {}; |
|
499 |
|
500 template <class T, class B = ::boost::detail::empty_base<T> > |
|
501 struct shiftable1 |
|
502 : left_shiftable1<T |
|
503 , right_shiftable1<T, B |
|
504 > > {}; |
|
505 |
|
506 template <class T, class U, class B = ::boost::detail::empty_base<T> > |
|
507 struct ring_operators2 |
|
508 : additive2<T, U |
|
509 , subtractable2_left<T, U |
|
510 , multipliable2<T, U, B |
|
511 > > > {}; |
|
512 |
|
513 template <class T, class B = ::boost::detail::empty_base<T> > |
|
514 struct ring_operators1 |
|
515 : additive1<T |
|
516 , multipliable1<T, B |
|
517 > > {}; |
|
518 |
|
519 template <class T, class U, class B = ::boost::detail::empty_base<T> > |
|
520 struct ordered_ring_operators2 |
|
521 : ring_operators2<T, U |
|
522 , totally_ordered2<T, U, B |
|
523 > > {}; |
|
524 |
|
525 template <class T, class B = ::boost::detail::empty_base<T> > |
|
526 struct ordered_ring_operators1 |
|
527 : ring_operators1<T |
|
528 , totally_ordered1<T, B |
|
529 > > {}; |
|
530 |
|
531 template <class T, class U, class B = ::boost::detail::empty_base<T> > |
|
532 struct field_operators2 |
|
533 : ring_operators2<T, U |
|
534 , dividable2<T, U |
|
535 , dividable2_left<T, U, B |
|
536 > > > {}; |
|
537 |
|
538 template <class T, class B = ::boost::detail::empty_base<T> > |
|
539 struct field_operators1 |
|
540 : ring_operators1<T |
|
541 , dividable1<T, B |
|
542 > > {}; |
|
543 |
|
544 template <class T, class U, class B = ::boost::detail::empty_base<T> > |
|
545 struct ordered_field_operators2 |
|
546 : field_operators2<T, U |
|
547 , totally_ordered2<T, U, B |
|
548 > > {}; |
|
549 |
|
550 template <class T, class B = ::boost::detail::empty_base<T> > |
|
551 struct ordered_field_operators1 |
|
552 : field_operators1<T |
|
553 , totally_ordered1<T, B |
|
554 > > {}; |
|
555 |
|
556 template <class T, class U, class B = ::boost::detail::empty_base<T> > |
|
557 struct 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 |
|
565 template <class T, class B = ::boost::detail::empty_base<T> > |
|
566 struct euclidian_ring_operators1 |
|
567 : ring_operators1<T |
|
568 , dividable1<T |
|
569 , modable1<T, B |
|
570 > > > {}; |
|
571 |
|
572 template <class T, class U, class B = ::boost::detail::empty_base<T> > |
|
573 struct ordered_euclidian_ring_operators2 |
|
574 : totally_ordered2<T, U |
|
575 , euclidian_ring_operators2<T, U, B |
|
576 > > {}; |
|
577 |
|
578 template <class T, class B = ::boost::detail::empty_base<T> > |
|
579 struct ordered_euclidian_ring_operators1 |
|
580 : totally_ordered1<T |
|
581 , euclidian_ring_operators1<T, B |
|
582 > > {}; |
|
583 |
|
584 template <class T, class P, class B = ::boost::detail::empty_base<T> > |
|
585 struct input_iteratable |
|
586 : equality_comparable1<T |
|
587 , incrementable<T |
|
588 , dereferenceable<T, P, B |
|
589 > > > {}; |
|
590 |
|
591 template <class T, class B = ::boost::detail::empty_base<T> > |
|
592 struct output_iteratable |
|
593 : incrementable<T, B |
|
594 > {}; |
|
595 |
|
596 template <class T, class P, class B = ::boost::detail::empty_base<T> > |
|
597 struct forward_iteratable |
|
598 : input_iteratable<T, P, B |
|
599 > {}; |
|
600 |
|
601 template <class T, class P, class B = ::boost::detail::empty_base<T> > |
|
602 struct 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) |
|
611 template <class T, class P, class D, class R, class B = ::boost::detail::empty_base<T> > |
|
612 struct 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 |
|
687 namespace 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. |
|
690 namespace 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. |
|
698 template<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) \ |
|
755 template <class T \ |
|
756 ,class U = T \ |
|
757 ,class B = ::boost::detail::empty_base<T> \ |
|
758 ,class O = typename is_chained_base<U>::value \ |
|
759 > \ |
|
760 struct template_name : template_name##2<T, U, B> {}; \ |
|
761 \ |
|
762 template<class T, class U, class B> \ |
|
763 struct template_name<T, U, B, ::boost::detail::true_t> \ |
|
764 : template_name##1<T, U> {}; \ |
|
765 \ |
|
766 template <class T, class B> \ |
|
767 struct template_name<T, T, B, ::boost::detail::false_t> \ |
|
768 : template_name##1<T, B> {}; \ |
|
769 \ |
|
770 template<class T, class U, class B, class O> \ |
|
771 struct is_chained_base< ::boost::template_name<T, U, B, O> > { \ |
|
772 typedef ::boost::detail::true_t value; \ |
|
773 }; \ |
|
774 \ |
|
775 BOOST_OPERATOR_TEMPLATE2(template_name##2) \ |
|
776 BOOST_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 |
|
798 namespace boost { |
|
799 |
|
800 BOOST_OPERATOR_TEMPLATE(less_than_comparable) |
|
801 BOOST_OPERATOR_TEMPLATE(equality_comparable) |
|
802 BOOST_OPERATOR_TEMPLATE(multipliable) |
|
803 BOOST_OPERATOR_TEMPLATE(addable) |
|
804 BOOST_OPERATOR_TEMPLATE(subtractable) |
|
805 BOOST_OPERATOR_TEMPLATE2(subtractable2_left) |
|
806 BOOST_OPERATOR_TEMPLATE(dividable) |
|
807 BOOST_OPERATOR_TEMPLATE2(dividable2_left) |
|
808 BOOST_OPERATOR_TEMPLATE(modable) |
|
809 BOOST_OPERATOR_TEMPLATE2(modable2_left) |
|
810 BOOST_OPERATOR_TEMPLATE(xorable) |
|
811 BOOST_OPERATOR_TEMPLATE(andable) |
|
812 BOOST_OPERATOR_TEMPLATE(orable) |
|
813 |
|
814 BOOST_OPERATOR_TEMPLATE1(incrementable) |
|
815 BOOST_OPERATOR_TEMPLATE1(decrementable) |
|
816 |
|
817 BOOST_OPERATOR_TEMPLATE2(dereferenceable) |
|
818 BOOST_OPERATOR_TEMPLATE3(indexable) |
|
819 |
|
820 BOOST_OPERATOR_TEMPLATE(left_shiftable) |
|
821 BOOST_OPERATOR_TEMPLATE(right_shiftable) |
|
822 BOOST_OPERATOR_TEMPLATE(equivalent) |
|
823 BOOST_OPERATOR_TEMPLATE(partially_ordered) |
|
824 |
|
825 BOOST_OPERATOR_TEMPLATE(totally_ordered) |
|
826 BOOST_OPERATOR_TEMPLATE(additive) |
|
827 BOOST_OPERATOR_TEMPLATE(multiplicative) |
|
828 BOOST_OPERATOR_TEMPLATE(integer_multiplicative) |
|
829 BOOST_OPERATOR_TEMPLATE(arithmetic) |
|
830 BOOST_OPERATOR_TEMPLATE(integer_arithmetic) |
|
831 BOOST_OPERATOR_TEMPLATE(bitwise) |
|
832 BOOST_OPERATOR_TEMPLATE1(unit_steppable) |
|
833 BOOST_OPERATOR_TEMPLATE(shiftable) |
|
834 BOOST_OPERATOR_TEMPLATE(ring_operators) |
|
835 BOOST_OPERATOR_TEMPLATE(ordered_ring_operators) |
|
836 BOOST_OPERATOR_TEMPLATE(field_operators) |
|
837 BOOST_OPERATOR_TEMPLATE(ordered_field_operators) |
|
838 BOOST_OPERATOR_TEMPLATE(euclidian_ring_operators) |
|
839 BOOST_OPERATOR_TEMPLATE(ordered_euclidian_ring_operators) |
|
840 BOOST_OPERATOR_TEMPLATE2(input_iteratable) |
|
841 BOOST_OPERATOR_TEMPLATE1(output_iteratable) |
|
842 BOOST_OPERATOR_TEMPLATE2(forward_iteratable) |
|
843 BOOST_OPERATOR_TEMPLATE2(bidirectional_iteratable) |
|
844 BOOST_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. |
|
858 template <class T, class U> |
|
859 struct operators2 |
|
860 : totally_ordered2<T,U |
|
861 , integer_arithmetic2<T,U |
|
862 , bitwise2<T,U |
|
863 > > > {}; |
|
864 |
|
865 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
|
866 template <class T, class U = T> |
|
867 struct operators : operators2<T, U> {}; |
|
868 |
|
869 template <class T> struct operators<T, T> |
|
870 #else |
|
871 template <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) ------------// |
|
882 template <class T, |
|
883 class V, |
|
884 class D = std::ptrdiff_t, |
|
885 class P = V const *, |
|
886 class R = V const &> |
|
887 struct input_iterator_helper |
|
888 : input_iteratable<T, P |
|
889 , boost::iterator<std::input_iterator_tag, V, D, P, R |
|
890 > > {}; |
|
891 |
|
892 template<class T> |
|
893 struct 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 |
|
902 template <class T, |
|
903 class V, |
|
904 class D = std::ptrdiff_t, |
|
905 class P = V*, |
|
906 class R = V&> |
|
907 struct forward_iterator_helper |
|
908 : forward_iteratable<T, P |
|
909 , boost::iterator<std::forward_iterator_tag, V, D, P, R |
|
910 > > {}; |
|
911 |
|
912 template <class T, |
|
913 class V, |
|
914 class D = std::ptrdiff_t, |
|
915 class P = V*, |
|
916 class R = V&> |
|
917 struct bidirectional_iterator_helper |
|
918 : bidirectional_iteratable<T, P |
|
919 , boost::iterator<std::bidirectional_iterator_tag, V, D, P, R |
|
920 > > {}; |
|
921 |
|
922 template <class T, |
|
923 class V, |
|
924 class D = std::ptrdiff_t, |
|
925 class P = V*, |
|
926 class R = V&> |
|
927 struct 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 |