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