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