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