]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Boost operators.hpp header file ----------------------------------------// |
2 | ||
3 | // (C) Copyright David Abrahams, Jeremy Siek, Daryle Walker 1999-2001. | |
b32b8144 | 4 | // (C) Copyright Daniel Frey 2002-2017. |
7c673cae FG |
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 | |
b32b8144 FG |
12 | // 23 Nov 17 Protect dereferenceable<> from overloaded operator&. |
13 | // 15 Oct 17 Adapted to C++17, replace std::iterator<> with manual | |
14 | // implementation. | |
7c673cae FG |
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> | |
b32b8144 | 102 | #include <boost/core/addressof.hpp> |
7c673cae FG |
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 | ||
20effc67 TL |
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 | ||
7c673cae FG |
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 | { | |
20effc67 TL |
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); } | |
7c673cae FG |
148 | }; |
149 | ||
150 | template <class T, class B = operators_detail::empty_base<T> > | |
151 | struct less_than_comparable1 : B | |
152 | { | |
20effc67 TL |
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); } | |
7c673cae FG |
156 | }; |
157 | ||
158 | template <class T, class U, class B = operators_detail::empty_base<T> > | |
159 | struct equality_comparable2 : B | |
160 | { | |
20effc67 TL |
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); } | |
7c673cae FG |
164 | }; |
165 | ||
166 | template <class T, class B = operators_detail::empty_base<T> > | |
167 | struct equality_comparable1 : B | |
168 | { | |
20effc67 | 169 | friend BOOST_OPERATORS_CONSTEXPR bool operator!=(const T& x, const T& y) { return !static_cast<bool>(x == y); } |
7c673cae FG |
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 | { | |
b32b8144 | 314 | return ::boost::addressof(*static_cast<const T&>(*this)); |
7c673cae FG |
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 | { | |
20effc67 | 372 | friend BOOST_OPERATORS_CONSTEXPR bool operator==(const T& x, const U& y) |
7c673cae FG |
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 | { | |
20effc67 | 381 | friend BOOST_OPERATORS_CONSTEXPR bool operator==(const T&x, const T&y) |
7c673cae FG |
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 | { | |
20effc67 | 390 | friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const T& x, const U& y) |
7c673cae | 391 | { return static_cast<bool>(x < y) || static_cast<bool>(x == y); } |
20effc67 | 392 | friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const T& x, const U& y) |
7c673cae | 393 | { return static_cast<bool>(x > y) || static_cast<bool>(x == y); } |
20effc67 | 394 | friend BOOST_OPERATORS_CONSTEXPR bool operator>(const U& x, const T& y) |
7c673cae | 395 | { return y < x; } |
20effc67 | 396 | friend BOOST_OPERATORS_CONSTEXPR bool operator<(const U& x, const T& y) |
7c673cae | 397 | { return y > x; } |
20effc67 | 398 | friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const U& x, const T& y) |
7c673cae | 399 | { return static_cast<bool>(y > x) || static_cast<bool>(y == x); } |
20effc67 | 400 | friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const U& x, const T& y) |
7c673cae FG |
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 | { | |
20effc67 | 407 | friend BOOST_OPERATORS_CONSTEXPR bool operator>(const T& x, const T& y) |
7c673cae | 408 | { return y < x; } |
20effc67 | 409 | friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const T& x, const T& y) |
7c673cae | 410 | { return static_cast<bool>(x < y) || static_cast<bool>(x == y); } |
20effc67 | 411 | friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const T& x, const T& y) |
7c673cae FG |
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) ------------// | |
b32b8144 FG |
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 | ||
7c673cae FG |
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 | |
b32b8144 | 860 | , iterator_helper<std::input_iterator_tag, V, D, P, R |
7c673cae FG |
861 | > > {}; |
862 | ||
863 | template<class T> | |
864 | struct output_iterator_helper | |
865 | : output_iteratable<T | |
b32b8144 | 866 | , iterator_helper<std::output_iterator_tag, void, void, void, void |
7c673cae FG |
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 | |
b32b8144 | 880 | , iterator_helper<std::forward_iterator_tag, V, D, P, R |
7c673cae FG |
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 | |
b32b8144 | 890 | , iterator_helper<std::bidirectional_iterator_tag, V, D, P, R |
7c673cae FG |
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 | |
b32b8144 | 900 | , iterator_helper<std::random_access_iterator_tag, V, D, P, R |
7c673cae FG |
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 |