]>
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 | |
1e59de90 TL |
115 | #elif defined __sun |
116 | #define BOOST_OPERATORS_CONSTEXPR | |
20effc67 TL |
117 | #else |
118 | #define BOOST_OPERATORS_CONSTEXPR BOOST_CONSTEXPR | |
119 | #endif | |
120 | ||
7c673cae FG |
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 | { | |
20effc67 TL |
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); } | |
7c673cae FG |
150 | }; |
151 | ||
152 | template <class T, class B = operators_detail::empty_base<T> > | |
153 | struct less_than_comparable1 : B | |
154 | { | |
20effc67 TL |
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); } | |
7c673cae FG |
158 | }; |
159 | ||
160 | template <class T, class U, class B = operators_detail::empty_base<T> > | |
161 | struct equality_comparable2 : B | |
162 | { | |
20effc67 TL |
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); } | |
7c673cae FG |
166 | }; |
167 | ||
168 | template <class T, class B = operators_detail::empty_base<T> > | |
169 | struct equality_comparable1 : B | |
170 | { | |
20effc67 | 171 | friend BOOST_OPERATORS_CONSTEXPR bool operator!=(const T& x, const T& y) { return !static_cast<bool>(x == y); } |
7c673cae FG |
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 | { | |
b32b8144 | 316 | return ::boost::addressof(*static_cast<const T&>(*this)); |
7c673cae FG |
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 | { | |
20effc67 | 374 | friend BOOST_OPERATORS_CONSTEXPR bool operator==(const T& x, const U& y) |
7c673cae FG |
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 | { | |
20effc67 | 383 | friend BOOST_OPERATORS_CONSTEXPR bool operator==(const T&x, const T&y) |
7c673cae FG |
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 | { | |
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 T& x, const U& y) |
7c673cae | 395 | { return static_cast<bool>(x > y) || static_cast<bool>(x == y); } |
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 y > x; } |
20effc67 | 400 | friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const U& x, const T& y) |
7c673cae | 401 | { return static_cast<bool>(y > x) || static_cast<bool>(y == x); } |
20effc67 | 402 | friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const U& x, const T& y) |
7c673cae FG |
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 | { | |
20effc67 | 409 | friend BOOST_OPERATORS_CONSTEXPR bool operator>(const T& x, const T& y) |
7c673cae | 410 | { return y < x; } |
20effc67 | 411 | friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const T& x, const T& y) |
7c673cae | 412 | { return static_cast<bool>(x < y) || static_cast<bool>(x == y); } |
20effc67 | 413 | friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const T& x, const T& y) |
7c673cae FG |
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) ------------// | |
b32b8144 FG |
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 | ||
7c673cae FG |
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 | |
b32b8144 | 862 | , iterator_helper<std::input_iterator_tag, V, D, P, R |
7c673cae FG |
863 | > > {}; |
864 | ||
865 | template<class T> | |
866 | struct output_iterator_helper | |
867 | : output_iteratable<T | |
b32b8144 | 868 | , iterator_helper<std::output_iterator_tag, void, void, void, void |
7c673cae FG |
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 | |
b32b8144 | 882 | , iterator_helper<std::forward_iterator_tag, V, D, P, R |
7c673cae FG |
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 | |
b32b8144 | 892 | , iterator_helper<std::bidirectional_iterator_tag, V, D, P, R |
7c673cae FG |
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 | |
b32b8144 | 902 | , iterator_helper<std::random_access_iterator_tag, V, D, P, R |
7c673cae FG |
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 |