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 | #else |
116 | #define BOOST_OPERATORS_CONSTEXPR BOOST_CONSTEXPR |
117 | #endif |
118 | |
119 | // In this section we supply the xxxx1 and xxxx2 forms of the operator |
120 | // templates, which are explicitly targeted at the 1-type-argument and |
121 | // 2-type-argument operator forms, respectively. |
122 | |
123 | namespace boost |
124 | { |
125 | namespace operators_impl |
126 | { |
127 | namespace operators_detail |
128 | { |
129 | |
130 | template <typename T> class empty_base {}; |
131 | |
132 | } // namespace operators_detail |
133 | |
134 | // Basic operator classes (contributed by Dave Abrahams) ------------------// |
135 | |
136 | // Note that friend functions defined in a class are implicitly inline. |
137 | // See the C++ std, 11.4 [class.friend] paragraph 5 |
138 | |
139 | template <class T, class U, class B = operators_detail::empty_base<T> > |
140 | struct less_than_comparable2 : B |
141 | { |
142 | friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const T& x, const U& y) { return !static_cast<bool>(x > y); } |
143 | friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const T& x, const U& y) { return !static_cast<bool>(x < y); } |
144 | friend BOOST_OPERATORS_CONSTEXPR bool operator>(const U& x, const T& y) { return y < x; } |
145 | friend BOOST_OPERATORS_CONSTEXPR bool operator<(const U& x, const T& y) { return y > x; } |
146 | friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const U& x, const T& y) { return !static_cast<bool>(y < x); } |
147 | friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const U& x, const T& y) { return !static_cast<bool>(y > x); } |
148 | }; |
149 | |
150 | template <class T, class B = operators_detail::empty_base<T> > |
151 | struct less_than_comparable1 : B |
152 | { |
153 | friend BOOST_OPERATORS_CONSTEXPR bool operator>(const T& x, const T& y) { return y < x; } |
154 | friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const T& x, const T& y) { return !static_cast<bool>(y < x); } |
155 | friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const T& x, const T& y) { return !static_cast<bool>(x < y); } |
156 | }; |
157 | |
158 | template <class T, class U, class B = operators_detail::empty_base<T> > |
159 | struct equality_comparable2 : B |
160 | { |
161 | friend BOOST_OPERATORS_CONSTEXPR bool operator==(const U& y, const T& x) { return x == y; } |
162 | friend BOOST_OPERATORS_CONSTEXPR bool operator!=(const U& y, const T& x) { return !static_cast<bool>(x == y); } |
163 | friend BOOST_OPERATORS_CONSTEXPR bool operator!=(const T& y, const U& x) { return !static_cast<bool>(y == x); } |
164 | }; |
165 | |
166 | template <class T, class B = operators_detail::empty_base<T> > |
167 | struct equality_comparable1 : B |
168 | { |
169 | friend BOOST_OPERATORS_CONSTEXPR bool operator!=(const T& x, const T& y) { return !static_cast<bool>(x == y); } |
170 | }; |
171 | |
172 | // A macro which produces "name_2left" from "name". |
173 | #define BOOST_OPERATOR2_LEFT(name) name##2##_##left |
174 | |
175 | // NRVO-friendly implementation (contributed by Daniel Frey) ---------------// |
176 | |
177 | #if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) |
178 | |
179 | // This is the optimal implementation for ISO/ANSI C++, |
180 | // but it requires the compiler to implement the NRVO. |
181 | // If the compiler has no NRVO, this is the best symmetric |
182 | // implementation available. |
183 | |
184 | #define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \ |
185 | template <class T, class U, class B = operators_detail::empty_base<T> > \ |
186 | struct NAME##2 : B \ |
187 | { \ |
188 | friend T operator OP( const T& lhs, const U& rhs ) \ |
189 | { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ |
190 | friend T operator OP( const U& lhs, const T& rhs ) \ |
191 | { T nrv( rhs ); nrv OP##= lhs; return nrv; } \ |
192 | }; \ |
193 | \ |
194 | template <class T, class B = operators_detail::empty_base<T> > \ |
195 | struct NAME##1 : B \ |
196 | { \ |
197 | friend T operator OP( const T& lhs, const T& rhs ) \ |
198 | { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ |
199 | }; |
200 | |
201 | #define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \ |
202 | template <class T, class U, class B = operators_detail::empty_base<T> > \ |
203 | struct NAME##2 : B \ |
204 | { \ |
205 | friend T operator OP( const T& lhs, const U& rhs ) \ |
206 | { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ |
207 | }; \ |
208 | \ |
209 | template <class T, class U, class B = operators_detail::empty_base<T> > \ |
210 | struct BOOST_OPERATOR2_LEFT(NAME) : B \ |
211 | { \ |
212 | friend T operator OP( const U& lhs, const T& rhs ) \ |
213 | { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ |
214 | }; \ |
215 | \ |
216 | template <class T, class B = operators_detail::empty_base<T> > \ |
217 | struct NAME##1 : B \ |
218 | { \ |
219 | friend T operator OP( const T& lhs, const T& rhs ) \ |
220 | { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ |
221 | }; |
222 | |
223 | #else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) |
224 | |
225 | // For compilers without NRVO the following code is optimal, but not |
226 | // symmetric! Note that the implementation of |
227 | // BOOST_OPERATOR2_LEFT(NAME) only looks cool, but doesn't provide |
228 | // optimization opportunities to the compiler :) |
229 | |
230 | #define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \ |
231 | template <class T, class U, class B = operators_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 | friend T operator OP( const U& lhs, T rhs ) { return rhs OP##= lhs; } \ |
236 | }; \ |
237 | \ |
238 | template <class T, class B = operators_detail::empty_base<T> > \ |
239 | struct NAME##1 : B \ |
240 | { \ |
241 | friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \ |
242 | }; |
243 | |
244 | #define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \ |
245 | template <class T, class U, class B = operators_detail::empty_base<T> > \ |
246 | struct NAME##2 : B \ |
247 | { \ |
248 | friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \ |
249 | }; \ |
250 | \ |
251 | template <class T, class U, class B = operators_detail::empty_base<T> > \ |
252 | struct BOOST_OPERATOR2_LEFT(NAME) : B \ |
253 | { \ |
254 | friend T operator OP( const U& lhs, const T& rhs ) \ |
255 | { return T( lhs ) OP##= rhs; } \ |
256 | }; \ |
257 | \ |
258 | template <class T, class B = operators_detail::empty_base<T> > \ |
259 | struct NAME##1 : B \ |
260 | { \ |
261 | friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \ |
262 | }; |
263 | |
264 | #endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) |
265 | |
266 | BOOST_BINARY_OPERATOR_COMMUTATIVE( multipliable, * ) |
267 | BOOST_BINARY_OPERATOR_COMMUTATIVE( addable, + ) |
268 | BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( subtractable, - ) |
269 | BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( dividable, / ) |
270 | BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( modable, % ) |
271 | BOOST_BINARY_OPERATOR_COMMUTATIVE( xorable, ^ ) |
272 | BOOST_BINARY_OPERATOR_COMMUTATIVE( andable, & ) |
273 | BOOST_BINARY_OPERATOR_COMMUTATIVE( orable, | ) |
274 | |
275 | #undef BOOST_BINARY_OPERATOR_COMMUTATIVE |
276 | #undef BOOST_BINARY_OPERATOR_NON_COMMUTATIVE |
277 | #undef BOOST_OPERATOR2_LEFT |
278 | |
279 | // incrementable and decrementable contributed by Jeremy Siek |
280 | |
281 | template <class T, class B = operators_detail::empty_base<T> > |
282 | struct incrementable : B |
283 | { |
284 | friend T operator++(T& x, int) |
285 | { |
286 | incrementable_type nrv(x); |
287 | ++x; |
288 | return nrv; |
289 | } |
290 | private: // The use of this typedef works around a Borland bug |
291 | typedef T incrementable_type; |
292 | }; |
293 | |
294 | template <class T, class B = operators_detail::empty_base<T> > |
295 | struct decrementable : B |
296 | { |
297 | friend T operator--(T& x, int) |
298 | { |
299 | decrementable_type nrv(x); |
300 | --x; |
301 | return nrv; |
302 | } |
303 | private: // The use of this typedef works around a Borland bug |
304 | typedef T decrementable_type; |
305 | }; |
306 | |
307 | // Iterator operator classes (contributed by Jeremy Siek) ------------------// |
308 | |
309 | template <class T, class P, class B = operators_detail::empty_base<T> > |
310 | struct dereferenceable : B |
311 | { |
312 | P operator->() const |
313 | { |
314 | return ::boost::addressof(*static_cast<const T&>(*this)); |
315 | } |
316 | }; |
317 | |
318 | template <class T, class I, class R, class B = operators_detail::empty_base<T> > |
319 | struct indexable : B |
320 | { |
321 | R operator[](I n) const |
322 | { |
323 | return *(static_cast<const T&>(*this) + n); |
324 | } |
325 | }; |
326 | |
327 | // More operator classes (contributed by Daryle Walker) --------------------// |
328 | // (NRVO-friendly implementation contributed by Daniel Frey) ---------------// |
329 | |
330 | #if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) |
331 | |
332 | #define BOOST_BINARY_OPERATOR( NAME, OP ) \ |
333 | template <class T, class U, class B = operators_detail::empty_base<T> > \ |
334 | struct NAME##2 : B \ |
335 | { \ |
336 | friend T operator OP( const T& lhs, const U& rhs ) \ |
337 | { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ |
338 | }; \ |
339 | \ |
340 | template <class T, class B = operators_detail::empty_base<T> > \ |
341 | struct NAME##1 : B \ |
342 | { \ |
343 | friend T operator OP( const T& lhs, const T& rhs ) \ |
344 | { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ |
345 | }; |
346 | |
347 | #else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) |
348 | |
349 | #define BOOST_BINARY_OPERATOR( NAME, OP ) \ |
350 | template <class T, class U, class B = operators_detail::empty_base<T> > \ |
351 | struct NAME##2 : B \ |
352 | { \ |
353 | friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \ |
354 | }; \ |
355 | \ |
356 | template <class T, class B = operators_detail::empty_base<T> > \ |
357 | struct NAME##1 : B \ |
358 | { \ |
359 | friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \ |
360 | }; |
361 | |
362 | #endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) |
363 | |
364 | BOOST_BINARY_OPERATOR( left_shiftable, << ) |
365 | BOOST_BINARY_OPERATOR( right_shiftable, >> ) |
366 | |
367 | #undef BOOST_BINARY_OPERATOR |
368 | |
369 | template <class T, class U, class B = operators_detail::empty_base<T> > |
370 | struct equivalent2 : B |
371 | { |
372 | friend BOOST_OPERATORS_CONSTEXPR bool operator==(const T& x, const U& y) |
373 | { |
374 | return !static_cast<bool>(x < y) && !static_cast<bool>(x > y); |
375 | } |
376 | }; |
377 | |
378 | template <class T, class B = operators_detail::empty_base<T> > |
379 | struct equivalent1 : B |
380 | { |
381 | friend BOOST_OPERATORS_CONSTEXPR bool operator==(const T&x, const T&y) |
382 | { |
383 | return !static_cast<bool>(x < y) && !static_cast<bool>(y < x); |
384 | } |
385 | }; |
386 | |
387 | template <class T, class U, class B = operators_detail::empty_base<T> > |
388 | struct partially_ordered2 : B |
389 | { |
390 | friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const T& x, const U& y) |
391 | { return static_cast<bool>(x < y) || static_cast<bool>(x == y); } |
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 U& x, const T& y) |
395 | { return y < x; } |
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 static_cast<bool>(y > x) || static_cast<bool>(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 | }; |
403 | |
404 | template <class T, class B = operators_detail::empty_base<T> > |
405 | struct partially_ordered1 : B |
406 | { |
407 | friend BOOST_OPERATORS_CONSTEXPR bool operator>(const T& x, const T& y) |
408 | { return y < x; } |
409 | friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const T& x, const T& y) |
410 | { return static_cast<bool>(x < y) || static_cast<bool>(x == y); } |
411 | friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const T& x, const T& y) |
412 | { return static_cast<bool>(y < x) || static_cast<bool>(x == y); } |
413 | }; |
414 | |
415 | // Combined operator classes (contributed by Daryle Walker) ----------------// |
416 | |
417 | template <class T, class U, class B = operators_detail::empty_base<T> > |
418 | struct totally_ordered2 |
419 | : less_than_comparable2<T, U |
420 | , equality_comparable2<T, U, B |
421 | > > {}; |
422 | |
423 | template <class T, class B = operators_detail::empty_base<T> > |
424 | struct totally_ordered1 |
425 | : less_than_comparable1<T |
426 | , equality_comparable1<T, B |
427 | > > {}; |
428 | |
429 | template <class T, class U, class B = operators_detail::empty_base<T> > |
430 | struct additive2 |
431 | : addable2<T, U |
432 | , subtractable2<T, U, B |
433 | > > {}; |
434 | |
435 | template <class T, class B = operators_detail::empty_base<T> > |
436 | struct additive1 |
437 | : addable1<T |
438 | , subtractable1<T, B |
439 | > > {}; |
440 | |
441 | template <class T, class U, class B = operators_detail::empty_base<T> > |
442 | struct multiplicative2 |
443 | : multipliable2<T, U |
444 | , dividable2<T, U, B |
445 | > > {}; |
446 | |
447 | template <class T, class B = operators_detail::empty_base<T> > |
448 | struct multiplicative1 |
449 | : multipliable1<T |
450 | , dividable1<T, B |
451 | > > {}; |
452 | |
453 | template <class T, class U, class B = operators_detail::empty_base<T> > |
454 | struct integer_multiplicative2 |
455 | : multiplicative2<T, U |
456 | , modable2<T, U, B |
457 | > > {}; |
458 | |
459 | template <class T, class B = operators_detail::empty_base<T> > |
460 | struct integer_multiplicative1 |
461 | : multiplicative1<T |
462 | , modable1<T, B |
463 | > > {}; |
464 | |
465 | template <class T, class U, class B = operators_detail::empty_base<T> > |
466 | struct arithmetic2 |
467 | : additive2<T, U |
468 | , multiplicative2<T, U, B |
469 | > > {}; |
470 | |
471 | template <class T, class B = operators_detail::empty_base<T> > |
472 | struct arithmetic1 |
473 | : additive1<T |
474 | , multiplicative1<T, B |
475 | > > {}; |
476 | |
477 | template <class T, class U, class B = operators_detail::empty_base<T> > |
478 | struct integer_arithmetic2 |
479 | : additive2<T, U |
480 | , integer_multiplicative2<T, U, B |
481 | > > {}; |
482 | |
483 | template <class T, class B = operators_detail::empty_base<T> > |
484 | struct integer_arithmetic1 |
485 | : additive1<T |
486 | , integer_multiplicative1<T, B |
487 | > > {}; |
488 | |
489 | template <class T, class U, class B = operators_detail::empty_base<T> > |
490 | struct bitwise2 |
491 | : xorable2<T, U |
492 | , andable2<T, U |
493 | , orable2<T, U, B |
494 | > > > {}; |
495 | |
496 | template <class T, class B = operators_detail::empty_base<T> > |
497 | struct bitwise1 |
498 | : xorable1<T |
499 | , andable1<T |
500 | , orable1<T, B |
501 | > > > {}; |
502 | |
503 | template <class T, class B = operators_detail::empty_base<T> > |
504 | struct unit_steppable |
505 | : incrementable<T |
506 | , decrementable<T, B |
507 | > > {}; |
508 | |
509 | template <class T, class U, class B = operators_detail::empty_base<T> > |
510 | struct shiftable2 |
511 | : left_shiftable2<T, U |
512 | , right_shiftable2<T, U, B |
513 | > > {}; |
514 | |
515 | template <class T, class B = operators_detail::empty_base<T> > |
516 | struct shiftable1 |
517 | : left_shiftable1<T |
518 | , right_shiftable1<T, B |
519 | > > {}; |
520 | |
521 | template <class T, class U, class B = operators_detail::empty_base<T> > |
522 | struct ring_operators2 |
523 | : additive2<T, U |
524 | , subtractable2_left<T, U |
525 | , multipliable2<T, U, B |
526 | > > > {}; |
527 | |
528 | template <class T, class B = operators_detail::empty_base<T> > |
529 | struct ring_operators1 |
530 | : additive1<T |
531 | , multipliable1<T, B |
532 | > > {}; |
533 | |
534 | template <class T, class U, class B = operators_detail::empty_base<T> > |
535 | struct ordered_ring_operators2 |
536 | : ring_operators2<T, U |
537 | , totally_ordered2<T, U, B |
538 | > > {}; |
539 | |
540 | template <class T, class B = operators_detail::empty_base<T> > |
541 | struct ordered_ring_operators1 |
542 | : ring_operators1<T |
543 | , totally_ordered1<T, B |
544 | > > {}; |
545 | |
546 | template <class T, class U, class B = operators_detail::empty_base<T> > |
547 | struct field_operators2 |
548 | : ring_operators2<T, U |
549 | , dividable2<T, U |
550 | , dividable2_left<T, U, B |
551 | > > > {}; |
552 | |
553 | template <class T, class B = operators_detail::empty_base<T> > |
554 | struct field_operators1 |
555 | : ring_operators1<T |
556 | , dividable1<T, B |
557 | > > {}; |
558 | |
559 | template <class T, class U, class B = operators_detail::empty_base<T> > |
560 | struct ordered_field_operators2 |
561 | : field_operators2<T, U |
562 | , totally_ordered2<T, U, B |
563 | > > {}; |
564 | |
565 | template <class T, class B = operators_detail::empty_base<T> > |
566 | struct ordered_field_operators1 |
567 | : field_operators1<T |
568 | , totally_ordered1<T, B |
569 | > > {}; |
570 | |
571 | template <class T, class U, class B = operators_detail::empty_base<T> > |
572 | struct euclidian_ring_operators2 |
573 | : ring_operators2<T, U |
574 | , dividable2<T, U |
575 | , dividable2_left<T, U |
576 | , modable2<T, U |
577 | , modable2_left<T, U, B |
578 | > > > > > {}; |
579 | |
580 | template <class T, class B = operators_detail::empty_base<T> > |
581 | struct euclidian_ring_operators1 |
582 | : ring_operators1<T |
583 | , dividable1<T |
584 | , modable1<T, B |
585 | > > > {}; |
586 | |
587 | template <class T, class U, class B = operators_detail::empty_base<T> > |
588 | struct ordered_euclidian_ring_operators2 |
589 | : totally_ordered2<T, U |
590 | , euclidian_ring_operators2<T, U, B |
591 | > > {}; |
592 | |
593 | template <class T, class B = operators_detail::empty_base<T> > |
594 | struct ordered_euclidian_ring_operators1 |
595 | : totally_ordered1<T |
596 | , euclidian_ring_operators1<T, B |
597 | > > {}; |
598 | |
599 | template <class T, class U, class B = operators_detail::empty_base<T> > |
600 | struct euclidean_ring_operators2 |
601 | : ring_operators2<T, U |
602 | , dividable2<T, U |
603 | , dividable2_left<T, U |
604 | , modable2<T, U |
605 | , modable2_left<T, U, B |
606 | > > > > > {}; |
607 | |
608 | template <class T, class B = operators_detail::empty_base<T> > |
609 | struct euclidean_ring_operators1 |
610 | : ring_operators1<T |
611 | , dividable1<T |
612 | , modable1<T, B |
613 | > > > {}; |
614 | |
615 | template <class T, class U, class B = operators_detail::empty_base<T> > |
616 | struct ordered_euclidean_ring_operators2 |
617 | : totally_ordered2<T, U |
618 | , euclidean_ring_operators2<T, U, B |
619 | > > {}; |
620 | |
621 | template <class T, class B = operators_detail::empty_base<T> > |
622 | struct ordered_euclidean_ring_operators1 |
623 | : totally_ordered1<T |
624 | , euclidean_ring_operators1<T, B |
625 | > > {}; |
626 | |
627 | template <class T, class P, class B = operators_detail::empty_base<T> > |
628 | struct input_iteratable |
629 | : equality_comparable1<T |
630 | , incrementable<T |
631 | , dereferenceable<T, P, B |
632 | > > > {}; |
633 | |
634 | template <class T, class B = operators_detail::empty_base<T> > |
635 | struct output_iteratable |
636 | : incrementable<T, B |
637 | > {}; |
638 | |
639 | template <class T, class P, class B = operators_detail::empty_base<T> > |
640 | struct forward_iteratable |
641 | : input_iteratable<T, P, B |
642 | > {}; |
643 | |
644 | template <class T, class P, class B = operators_detail::empty_base<T> > |
645 | struct bidirectional_iteratable |
646 | : forward_iteratable<T, P |
647 | , decrementable<T, B |
648 | > > {}; |
649 | |
650 | // To avoid repeated derivation from equality_comparable, |
651 | // which is an indirect base class of bidirectional_iterable, |
652 | // random_access_iteratable must not be derived from totally_ordered1 |
653 | // but from less_than_comparable1 only. (Helmut Zeisel, 02-Dec-2001) |
654 | template <class T, class P, class D, class R, class B = operators_detail::empty_base<T> > |
655 | struct random_access_iteratable |
656 | : bidirectional_iteratable<T, P |
657 | , less_than_comparable1<T |
658 | , additive2<T, D |
659 | , indexable<T, D, R, B |
660 | > > > > {}; |
661 | |
662 | |
663 | // |
664 | // Here's where we put it all together, defining the xxxx forms of the templates. |
665 | // We also define specializations of is_chained_base<> for |
666 | // the xxxx, xxxx1, and xxxx2 templates. |
667 | // |
668 | |
669 | namespace operators_detail |
670 | { |
671 | |
672 | // A type parameter is used instead of a plain bool because Borland's compiler |
673 | // didn't cope well with the more obvious non-type template parameter. |
674 | struct true_t {}; |
675 | struct false_t {}; |
676 | |
677 | } // namespace operators_detail |
678 | |
679 | // is_chained_base<> - a traits class used to distinguish whether an operator |
680 | // template argument is being used for base class chaining, or is specifying a |
681 | // 2nd argument type. |
682 | |
683 | // Unspecialized version assumes that most types are not being used for base |
684 | // class chaining. We specialize for the operator templates defined in this |
685 | // library. |
686 | template<class T> struct is_chained_base { |
687 | typedef operators_detail::false_t value; |
688 | }; |
689 | |
690 | // Provide a specialization of 'is_chained_base<>' |
691 | // for a 4-type-argument operator template. |
692 | # define BOOST_OPERATOR_TEMPLATE4(template_name4) \ |
693 | template<class T, class U, class V, class W, class B> \ |
694 | struct is_chained_base< template_name4<T, U, V, W, B> > { \ |
695 | typedef operators_detail::true_t value; \ |
696 | }; |
697 | |
698 | // Provide a specialization of 'is_chained_base<>' |
699 | // for a 3-type-argument operator template. |
700 | # define BOOST_OPERATOR_TEMPLATE3(template_name3) \ |
701 | template<class T, class U, class V, class B> \ |
702 | struct is_chained_base< template_name3<T, U, V, B> > { \ |
703 | typedef operators_detail::true_t value; \ |
704 | }; |
705 | |
706 | // Provide a specialization of 'is_chained_base<>' |
707 | // for a 2-type-argument operator template. |
708 | # define BOOST_OPERATOR_TEMPLATE2(template_name2) \ |
709 | template<class T, class U, class B> \ |
710 | struct is_chained_base< template_name2<T, U, B> > { \ |
711 | typedef operators_detail::true_t value; \ |
712 | }; |
713 | |
714 | // Provide a specialization of 'is_chained_base<>' |
715 | // for a 1-type-argument operator template. |
716 | # define BOOST_OPERATOR_TEMPLATE1(template_name1) \ |
717 | template<class T, class B> \ |
718 | struct is_chained_base< template_name1<T, B> > { \ |
719 | typedef operators_detail::true_t value; \ |
720 | }; |
721 | |
722 | // BOOST_OPERATOR_TEMPLATE(template_name) defines template_name<> such that it |
723 | // can be used for specifying both 1-argument and 2-argument forms. Requires the |
724 | // existence of two previously defined class templates named '<template_name>1' |
725 | // and '<template_name>2' which must implement the corresponding 1- and 2- |
726 | // argument forms. |
727 | // |
728 | // The template type parameter O == is_chained_base<U>::value is used to |
729 | // distinguish whether the 2nd argument to <template_name> is being used for |
730 | // base class chaining from another boost operator template or is describing a |
731 | // 2nd operand type. O == true_t only when U is actually an another operator |
732 | // template from the library. Partial specialization is used to select an |
733 | // implementation in terms of either '<template_name>1' or '<template_name>2'. |
734 | // |
735 | |
736 | # define BOOST_OPERATOR_TEMPLATE(template_name) \ |
737 | template <class T \ |
738 | ,class U = T \ |
739 | ,class B = operators_detail::empty_base<T> \ |
740 | ,class O = typename is_chained_base<U>::value \ |
741 | > \ |
742 | struct template_name; \ |
743 | \ |
744 | template<class T, class U, class B> \ |
745 | struct template_name<T, U, B, operators_detail::false_t> \ |
746 | : template_name##2<T, U, B> {}; \ |
747 | \ |
748 | template<class T, class U> \ |
749 | struct template_name<T, U, operators_detail::empty_base<T>, operators_detail::true_t> \ |
750 | : template_name##1<T, U> {}; \ |
751 | \ |
752 | template <class T, class B> \ |
753 | struct template_name<T, T, B, operators_detail::false_t> \ |
754 | : template_name##1<T, B> {}; \ |
755 | \ |
756 | template<class T, class U, class B, class O> \ |
757 | struct is_chained_base< template_name<T, U, B, O> > { \ |
758 | typedef operators_detail::true_t value; \ |
759 | }; \ |
760 | \ |
761 | BOOST_OPERATOR_TEMPLATE2(template_name##2) \ |
762 | BOOST_OPERATOR_TEMPLATE1(template_name##1) |
763 | |
764 | BOOST_OPERATOR_TEMPLATE(less_than_comparable) |
765 | BOOST_OPERATOR_TEMPLATE(equality_comparable) |
766 | BOOST_OPERATOR_TEMPLATE(multipliable) |
767 | BOOST_OPERATOR_TEMPLATE(addable) |
768 | BOOST_OPERATOR_TEMPLATE(subtractable) |
769 | BOOST_OPERATOR_TEMPLATE2(subtractable2_left) |
770 | BOOST_OPERATOR_TEMPLATE(dividable) |
771 | BOOST_OPERATOR_TEMPLATE2(dividable2_left) |
772 | BOOST_OPERATOR_TEMPLATE(modable) |
773 | BOOST_OPERATOR_TEMPLATE2(modable2_left) |
774 | BOOST_OPERATOR_TEMPLATE(xorable) |
775 | BOOST_OPERATOR_TEMPLATE(andable) |
776 | BOOST_OPERATOR_TEMPLATE(orable) |
777 | |
778 | BOOST_OPERATOR_TEMPLATE1(incrementable) |
779 | BOOST_OPERATOR_TEMPLATE1(decrementable) |
780 | |
781 | BOOST_OPERATOR_TEMPLATE2(dereferenceable) |
782 | BOOST_OPERATOR_TEMPLATE3(indexable) |
783 | |
784 | BOOST_OPERATOR_TEMPLATE(left_shiftable) |
785 | BOOST_OPERATOR_TEMPLATE(right_shiftable) |
786 | BOOST_OPERATOR_TEMPLATE(equivalent) |
787 | BOOST_OPERATOR_TEMPLATE(partially_ordered) |
788 | |
789 | BOOST_OPERATOR_TEMPLATE(totally_ordered) |
790 | BOOST_OPERATOR_TEMPLATE(additive) |
791 | BOOST_OPERATOR_TEMPLATE(multiplicative) |
792 | BOOST_OPERATOR_TEMPLATE(integer_multiplicative) |
793 | BOOST_OPERATOR_TEMPLATE(arithmetic) |
794 | BOOST_OPERATOR_TEMPLATE(integer_arithmetic) |
795 | BOOST_OPERATOR_TEMPLATE(bitwise) |
796 | BOOST_OPERATOR_TEMPLATE1(unit_steppable) |
797 | BOOST_OPERATOR_TEMPLATE(shiftable) |
798 | BOOST_OPERATOR_TEMPLATE(ring_operators) |
799 | BOOST_OPERATOR_TEMPLATE(ordered_ring_operators) |
800 | BOOST_OPERATOR_TEMPLATE(field_operators) |
801 | BOOST_OPERATOR_TEMPLATE(ordered_field_operators) |
802 | BOOST_OPERATOR_TEMPLATE(euclidian_ring_operators) |
803 | BOOST_OPERATOR_TEMPLATE(ordered_euclidian_ring_operators) |
804 | BOOST_OPERATOR_TEMPLATE(euclidean_ring_operators) |
805 | BOOST_OPERATOR_TEMPLATE(ordered_euclidean_ring_operators) |
806 | BOOST_OPERATOR_TEMPLATE2(input_iteratable) |
807 | BOOST_OPERATOR_TEMPLATE1(output_iteratable) |
808 | BOOST_OPERATOR_TEMPLATE2(forward_iteratable) |
809 | BOOST_OPERATOR_TEMPLATE2(bidirectional_iteratable) |
810 | BOOST_OPERATOR_TEMPLATE4(random_access_iteratable) |
811 | |
812 | #undef BOOST_OPERATOR_TEMPLATE |
813 | #undef BOOST_OPERATOR_TEMPLATE4 |
814 | #undef BOOST_OPERATOR_TEMPLATE3 |
815 | #undef BOOST_OPERATOR_TEMPLATE2 |
816 | #undef BOOST_OPERATOR_TEMPLATE1 |
817 | |
818 | template <class T, class U> |
819 | struct operators2 |
820 | : totally_ordered2<T,U |
821 | , integer_arithmetic2<T,U |
822 | , bitwise2<T,U |
823 | > > > {}; |
824 | |
825 | template <class T, class U = T> |
826 | struct operators : operators2<T, U> {}; |
827 | |
828 | template <class T> struct operators<T, T> |
829 | : totally_ordered<T |
830 | , integer_arithmetic<T |
831 | , bitwise<T |
832 | , unit_steppable<T |
833 | > > > > {}; |
834 | |
835 | // Iterator helper classes (contributed by Jeremy Siek) -------------------// |
836 | // (Input and output iterator helpers contributed by Daryle Walker) -------// |
837 | // (Changed to use combined operator classes by Daryle Walker) ------------// |
838 | // (Adapted to C++17 by Daniel Frey) --------------------------------------// |
839 | template <class Category, |
840 | class T, |
841 | class Distance = std::ptrdiff_t, |
842 | class Pointer = T*, |
843 | class Reference = T&> |
844 | struct iterator_helper |
845 | { |
846 | typedef Category iterator_category; |
847 | typedef T value_type; |
848 | typedef Distance difference_type; |
849 | typedef Pointer pointer; |
850 | typedef Reference reference; |
851 | }; |
852 | |
853 | template <class T, |
854 | class V, |
855 | class D = std::ptrdiff_t, |
856 | class P = V const *, |
857 | class R = V const &> |
858 | struct input_iterator_helper |
859 | : input_iteratable<T, P |
860 | , iterator_helper<std::input_iterator_tag, V, D, P, R |
861 | > > {}; |
862 | |
863 | template<class T> |
864 | struct output_iterator_helper |
865 | : output_iteratable<T |
866 | , iterator_helper<std::output_iterator_tag, void, void, void, void |
867 | > > |
868 | { |
869 | T& operator*() { return static_cast<T&>(*this); } |
870 | T& operator++() { return static_cast<T&>(*this); } |
871 | }; |
872 | |
873 | template <class T, |
874 | class V, |
875 | class D = std::ptrdiff_t, |
876 | class P = V*, |
877 | class R = V&> |
878 | struct forward_iterator_helper |
879 | : forward_iteratable<T, P |
880 | , iterator_helper<std::forward_iterator_tag, V, D, P, R |
881 | > > {}; |
882 | |
883 | template <class T, |
884 | class V, |
885 | class D = std::ptrdiff_t, |
886 | class P = V*, |
887 | class R = V&> |
888 | struct bidirectional_iterator_helper |
889 | : bidirectional_iteratable<T, P |
890 | , iterator_helper<std::bidirectional_iterator_tag, V, D, P, R |
891 | > > {}; |
892 | |
893 | template <class T, |
894 | class V, |
895 | class D = std::ptrdiff_t, |
896 | class P = V*, |
897 | class R = V&> |
898 | struct random_access_iterator_helper |
899 | : random_access_iteratable<T, P, D, R |
900 | , iterator_helper<std::random_access_iterator_tag, V, D, P, R |
901 | > > |
902 | { |
903 | friend D requires_difference_operator(const T& x, const T& y) { |
904 | return x - y; |
905 | } |
906 | }; // random_access_iterator_helper |
907 | |
908 | } // namespace operators_impl |
909 | using namespace operators_impl; |
910 | |
911 | } // namespace boost |
912 | |
913 | #if defined(__sgi) && !defined(__GNUC__) |
914 | #pragma reset woff 1234 |
915 | #endif |
916 | |
917 | #endif // BOOST_NO_OPERATORS_IN_NAMESPACE |
918 | #endif // BOOST_OPERATORS_HPP |
919 | |