]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/type_erasure/include/boost/type_erasure/operators.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / type_erasure / include / boost / type_erasure / operators.hpp
1 // Boost.TypeErasure library
2 //
3 // Copyright 2011 Steven Watanabe
4 //
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 // $Id$
10
11 #ifndef BOOST_TYPE_ERASURE_OPERATORS_HPP_INCLUDED
12 #define BOOST_TYPE_ERASURE_OPERATORS_HPP_INCLUDED
13
14 #include <iosfwd>
15 #include <boost/utility/enable_if.hpp>
16 #include <boost/type_erasure/detail/const.hpp>
17 #include <boost/type_erasure/call.hpp>
18 #include <boost/type_erasure/concept_interface.hpp>
19 #include <boost/type_erasure/placeholder.hpp>
20 #include <boost/type_erasure/concept_of.hpp>
21 #include <boost/type_erasure/derived.hpp>
22 #include <boost/type_erasure/rebind_any.hpp>
23 #include <boost/type_erasure/param.hpp>
24 #include <boost/type_erasure/check_match.hpp>
25 #include <boost/type_erasure/relaxed.hpp>
26 #include <boost/type_erasure/typeid_of.hpp>
27
28 namespace boost {
29 namespace type_erasure {
30
31 template<class Concept, class Placeholder>
32 class any;
33
34 /** INTERNAL ONLY */
35 #define BOOST_TYPE_ERASURE_UNARY_INPLACE_OPERATOR(name, op) \
36 template<class T = _self> \
37 struct name \
38 { \
39 static void apply(T& arg) { op arg; } \
40 }; \
41 \
42 template<class T, class Base> \
43 struct concept_interface<name<T>, Base, T, \
44 typename ::boost::enable_if< \
45 detail::should_be_non_const<T, Base> \
46 >::type \
47 > : Base \
48 { \
49 typedef typename ::boost::type_erasure::derived<Base>::type _derived; \
50 _derived& operator op() \
51 { \
52 ::boost::type_erasure::call(name<T>(), *this); \
53 return static_cast<_derived&>(*this); \
54 } \
55 typename ::boost::type_erasure::rebind_any<Base, T>::type operator op(int) \
56 { \
57 typename ::boost::type_erasure::rebind_any<Base, T>::type result( \
58 static_cast<_derived&>(*this)); \
59 ::boost::type_erasure::call(name<T>(), *this); \
60 return result; \
61 } \
62 }; \
63 \
64 template<class T, class Base> \
65 struct concept_interface<name<T>, Base, T, \
66 typename ::boost::enable_if< \
67 detail::should_be_const<T, Base> \
68 >::type \
69 > : Base \
70 { \
71 typedef typename ::boost::type_erasure::derived<Base>::type _derived; \
72 const _derived& operator op() const \
73 { \
74 ::boost::type_erasure::call(name<T>(), *this); \
75 return static_cast<const _derived&>(*this); \
76 } \
77 typename ::boost::type_erasure::rebind_any<Base, T>::type operator op(int) const \
78 { \
79 typename ::boost::type_erasure::rebind_any<Base, T>::type result( \
80 static_cast<const _derived&>(*this)); \
81 ::boost::type_erasure::call(name<T>(), *this); \
82 return result; \
83 } \
84 };
85
86 /**
87 * The @ref incrementable concept allow pre and
88 * post increment on an @ref any. The contained
89 * type must provide a pre-increment operator.
90 */
91 BOOST_TYPE_ERASURE_UNARY_INPLACE_OPERATOR(incrementable, ++)
92 /**
93 * The @ref decrementable concept allow pre and
94 * post decrement on an @ref any. The contained
95 * type must provide a pre-decrement operator.
96 */
97 BOOST_TYPE_ERASURE_UNARY_INPLACE_OPERATOR(decrementable, --)
98
99 #undef BOOST_TYPE_ERASURE_UNARY_INPLACE_OPERATOR
100
101 /** INTERNAL ONLY */
102 #define BOOST_TYPE_ERASURE_UNARY_OPERATOR(name, op) \
103 template<class T = _self, class R = T> \
104 struct name \
105 { \
106 static R apply(const T& arg) { return op arg; } \
107 }; \
108 \
109 template<class T, class R, class Base> \
110 struct concept_interface<name<T, R>, Base, T> : Base \
111 { \
112 typename ::boost::type_erasure::rebind_any<Base, R>::type operator op() const \
113 { \
114 return ::boost::type_erasure::call(name<T, R>(), *this); \
115 } \
116 };
117
118 /**
119 * The @ref complementable concept allow use of the bitwise
120 * complement operator on an @ref any.
121 */
122 BOOST_TYPE_ERASURE_UNARY_OPERATOR(complementable, ~)
123 /**
124 * The @ref negatable concept allow use of the unary
125 * minus operator on an @ref any.
126 */
127 BOOST_TYPE_ERASURE_UNARY_OPERATOR(negatable, -)
128
129 #undef BOOST_TYPE_ERASURE_UNARY_OPERATOR
130
131 template<class R, class T = _self>
132 struct dereferenceable
133 {
134 static R apply(const T& arg) { return *arg; }
135 };
136
137 /// \cond show_operators
138
139 template<class R, class T, class Base>
140 struct concept_interface<dereferenceable<R, T>, Base, T> : Base
141 {
142 typename ::boost::type_erasure::rebind_any<Base, R>::type operator*() const
143 {
144 return ::boost::type_erasure::call(dereferenceable<R, T>(), *this);
145 }
146 };
147
148 /// \endcond
149
150 /** INTERNAL ONLY */
151 #define BOOST_TYPE_ERASURE_BINARY_OPERATOR(name, op) \
152 template<class T = _self, class U = T, class R = T> \
153 struct name \
154 { \
155 static R apply(const T& lhs, const U& rhs) { return lhs op rhs; } \
156 }; \
157 \
158 template<class T, class U, class R, class Base> \
159 struct concept_interface<name<T, U, R>, Base, T> : Base \
160 { \
161 friend typename rebind_any<Base, R>::type \
162 operator op(const typename derived<Base>::type& lhs, \
163 typename as_param<Base, const U&>::type rhs) \
164 { \
165 return ::boost::type_erasure::call(name<T, U, R>(), lhs, rhs); \
166 } \
167 }; \
168 \
169 template<class T, class U, class R, class Base> \
170 struct concept_interface< \
171 name<T, U, R>, \
172 Base, \
173 U, \
174 typename ::boost::disable_if< \
175 ::boost::type_erasure::is_placeholder<T> >::type \
176 > : Base \
177 { \
178 friend typename rebind_any<Base, R>::type \
179 operator op(const T& lhs, \
180 const typename derived<Base>::type& rhs) \
181 { \
182 return ::boost::type_erasure::call(name<T, U, R>(), lhs, rhs); \
183 } \
184 };
185
186 BOOST_TYPE_ERASURE_BINARY_OPERATOR(addable, +)
187 BOOST_TYPE_ERASURE_BINARY_OPERATOR(subtractable, -)
188 BOOST_TYPE_ERASURE_BINARY_OPERATOR(multipliable, *)
189 BOOST_TYPE_ERASURE_BINARY_OPERATOR(dividable, /)
190 BOOST_TYPE_ERASURE_BINARY_OPERATOR(modable, %)
191 BOOST_TYPE_ERASURE_BINARY_OPERATOR(left_shiftable, <<)
192 BOOST_TYPE_ERASURE_BINARY_OPERATOR(right_shiftable, >>)
193 BOOST_TYPE_ERASURE_BINARY_OPERATOR(bitandable, &)
194 BOOST_TYPE_ERASURE_BINARY_OPERATOR(bitorable, |)
195 BOOST_TYPE_ERASURE_BINARY_OPERATOR(bitxorable, ^)
196
197 #undef BOOST_TYPE_ERASURE_BINARY_OPERATOR
198
199 /** INTERNAL ONLY */
200 #define BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(name, op) \
201 template<class T = _self, class U = T> \
202 struct name \
203 { \
204 static void apply(T& lhs, const U& rhs) { lhs op rhs; } \
205 }; \
206 \
207 template<class T, class U, class Base> \
208 struct concept_interface<name<T, U>, Base, T, \
209 typename ::boost::disable_if< \
210 ::boost::is_same< \
211 typename ::boost::type_erasure::placeholder_of<Base>::type, \
212 const T& \
213 > \
214 >::type \
215 > : Base \
216 { \
217 friend typename detail::non_const_this_param<Base>::type& \
218 operator op(typename detail::non_const_this_param<Base>::type& lhs, \
219 typename as_param<Base, const U&>::type rhs) \
220 { \
221 ::boost::type_erasure::call(name<T, U>(),lhs, rhs); \
222 return lhs; \
223 } \
224 }; \
225 \
226 template<class T, class U, class Base> \
227 struct concept_interface< \
228 name<T, U>, \
229 Base, \
230 U, \
231 typename ::boost::disable_if< \
232 ::boost::type_erasure::is_placeholder<T> >::type \
233 > : Base \
234 { \
235 friend T& \
236 operator op(T& lhs, const typename derived<Base>::type& rhs) \
237 { \
238 ::boost::type_erasure::call(name<T, U>(),lhs, rhs); \
239 return lhs; \
240 } \
241 };
242
243 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(add_assignable, +=)
244 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(subtract_assignable, -=)
245 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(multiply_assignable, *=)
246 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(divide_assignable, /=)
247 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(mod_assignable, %=)
248 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(left_shift_assignable, <<=)
249 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(right_shift_assignable, >>=)
250 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(bitand_assignable, &=)
251 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(bitor_assignable, |=)
252 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(bitxor_assignable, ^=)
253
254 #undef BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR
255
256 template<class T = _self, class U = T>
257 struct equality_comparable
258 {
259 static bool apply(const T& lhs, const U& rhs) { return lhs == rhs; }
260 };
261
262 /// \cond show_operators
263
264 template<class T, class U, class Base>
265 struct concept_interface<equality_comparable<T, U>, Base, T> : Base
266 {
267 friend bool operator==(const typename derived<Base>::type& lhs,
268 typename as_param<Base, const U&>::type rhs)
269 {
270 if(::boost::type_erasure::check_match(equality_comparable<T, U>(), lhs, rhs)) {
271 return ::boost::type_erasure::unchecked_call(equality_comparable<T, U>(), lhs, rhs);
272 } else {
273 return false;
274 }
275 }
276 friend bool operator!=(const typename derived<Base>::type& lhs,
277 typename as_param<Base, const U&>::type rhs)
278 {
279 return !(lhs == rhs);
280 }
281 };
282
283 template<class T, class U, class Base>
284 struct concept_interface<
285 equality_comparable<T, U>,
286 Base,
287 U,
288 typename ::boost::disable_if< ::boost::type_erasure::is_placeholder<T> >::type
289 > : Base
290 {
291 friend bool operator==(const T& lhs, const typename derived<Base>::type& rhs)
292 {
293 return ::boost::type_erasure::call(equality_comparable<T, U>(), lhs, rhs);
294 }
295 friend bool operator!=(const T& lhs, const typename derived<Base>::type& rhs)
296 {
297 return !(lhs == rhs);
298 }
299 };
300
301 /// \endcond
302
303 template<class T = _self, class U = T>
304 struct less_than_comparable
305 {
306 static bool apply(const T& lhs, const U& rhs) { return lhs < rhs; }
307 };
308
309 namespace detail {
310
311 template<class F, class T, class U>
312 bool less_impl(const F& f, const T& lhs, const U& rhs, ::boost::mpl::true_)
313 {
314 if(::boost::type_erasure::check_match(f, lhs, rhs)) {
315 return ::boost::type_erasure::unchecked_call(f, lhs, rhs);
316 } else {
317 return ::boost::type_erasure::typeid_of(
318 static_cast<const typename derived<T>::type&>(lhs)
319 ).before(
320 ::boost::type_erasure::typeid_of(
321 static_cast<const typename derived<U>::type&>(rhs)
322 )
323 ) != false;
324 }
325 }
326
327 template<class F, class T, class U>
328 bool less_impl(const F& f, const T& lhs, const U& rhs, ::boost::mpl::false_)
329 {
330 return ::boost::type_erasure::call(f, lhs, rhs);
331 }
332
333 }
334
335 /// \cond show_operators
336
337 template<class T, class Base>
338 struct concept_interface<less_than_comparable<T, T>, Base, T> : Base
339 {
340 friend bool operator<(const typename derived<Base>::type& lhs,
341 typename as_param<Base, const T&>::type rhs)
342 {
343 return ::boost::type_erasure::detail::less_impl(
344 less_than_comparable<T, T>(),
345 lhs, rhs,
346 ::boost::type_erasure::is_relaxed<
347 typename ::boost::type_erasure::concept_of<Base>::type>());
348 }
349 friend bool operator>=(const typename derived<Base>::type& lhs,
350 typename as_param<Base, const T&>::type rhs)
351 {
352 return !(lhs < rhs);
353 }
354 friend bool operator>(typename as_param<Base, const T&>::type lhs,
355 const typename derived<Base>::type& rhs)
356 {
357 return rhs < lhs;
358 }
359 friend bool operator<=(typename as_param<Base, const T&>::type lhs,
360 const typename derived<Base>::type& rhs)
361 {
362 return !(rhs < lhs);
363 }
364 };
365
366 template<class T, class U, class Base>
367 struct concept_interface<less_than_comparable<T, U>, Base, T> : Base
368 {
369 friend bool operator<(const typename derived<Base>::type& lhs,
370 typename as_param<Base, const U&>::type rhs)
371 {
372 return ::boost::type_erasure::call(less_than_comparable<T, U>(), lhs, rhs);
373 }
374 friend bool operator>=(const typename derived<Base>::type& lhs,
375 typename as_param<Base, const U&>::type rhs)
376 {
377 return !(lhs < rhs);
378 }
379 friend bool operator>(typename as_param<Base, const U&>::type lhs,
380 const typename derived<Base>::type& rhs)
381 {
382 return rhs < lhs;
383 }
384 friend bool operator<=(typename as_param<Base, const U&>::type lhs,
385 const typename derived<Base>::type& rhs)
386 {
387 return !(rhs < lhs);
388 }
389 };
390
391 template<class T, class U, class Base>
392 struct concept_interface<
393 less_than_comparable<T, U>,
394 Base,
395 U,
396 typename ::boost::disable_if< ::boost::type_erasure::is_placeholder<T> >::type
397 > : Base
398 {
399 friend bool operator<(const T& lhs, const typename derived<Base>::type& rhs)
400 {
401 return ::boost::type_erasure::call(less_than_comparable<T, U>(), lhs, rhs);
402 }
403 friend bool operator>=(const T& lhs, const typename derived<Base>::type& rhs)
404 {
405 return !(lhs < rhs);
406 }
407 friend bool operator>(const typename derived<Base>::type& lhs, const T& rhs)
408 {
409 return rhs < lhs;
410 }
411 friend bool operator<=(const typename derived<Base>::type& lhs, const T& rhs)
412 {
413 return !(rhs < lhs);
414 }
415 };
416
417 /// \endcond
418
419 template<class R, class T = _self, class N = std::ptrdiff_t>
420 struct subscriptable
421 {
422 static R apply(T& arg, const N& index) { return arg[index]; }
423 };
424
425 /// \cond show_operators
426
427 template<class R, class T, class N, class Base>
428 struct concept_interface<subscriptable<R, T, N>, Base, typename ::boost::remove_const<T>::type,
429 typename ::boost::enable_if<
430 ::boost::type_erasure::detail::should_be_non_const<T, Base>
431 >::type
432 > : Base
433 {
434 typename ::boost::type_erasure::rebind_any<Base, R>::type operator[](
435 typename ::boost::type_erasure::as_param<Base, const N&>::type index)
436 {
437 return ::boost::type_erasure::call(subscriptable<R, T, N>(), *this, index);
438 }
439 };
440
441 template<class R, class T, class N, class Base>
442 struct concept_interface<subscriptable<R, T, N>, Base, typename ::boost::remove_const<T>::type,
443 typename ::boost::enable_if<
444 ::boost::type_erasure::detail::should_be_const<T, Base>
445 >::type
446 > : Base
447 {
448 typename ::boost::type_erasure::rebind_any<Base, R>::type operator[](
449 typename ::boost::type_erasure::as_param<Base, const N&>::type index) const
450 {
451 return ::boost::type_erasure::call(subscriptable<R, const T, N>(), *this, index);
452 }
453 };
454
455 /// \endcond
456
457 /**
458 * The @ref ostreamable concept allows an @ref any to be
459 * written to a @c std::ostream.
460 */
461 template<class Os = std::ostream, class T = _self>
462 struct ostreamable
463 {
464 static void apply(Os& out, const T& arg) { out << arg; }
465 };
466
467 /// \cond show_operators
468
469 template<class Base, class Os, class T>
470 struct concept_interface<ostreamable<Os, T>, Base, Os> : Base
471 {
472 friend typename detail::non_const_this_param<Base>::type&
473 operator<<(typename detail::non_const_this_param<Base>::type& lhs,
474 typename ::boost::type_erasure::as_param<Base, const T&>::type rhs)
475 {
476 ::boost::type_erasure::call(ostreamable<Os, T>(), lhs, rhs);
477 return lhs;
478 }
479 };
480
481 template<class Base, class Os, class T>
482 struct concept_interface<
483 ostreamable<Os, T>,
484 Base,
485 T,
486 typename ::boost::disable_if< ::boost::type_erasure::is_placeholder<Os> >::type
487 > : Base
488 {
489 friend Os&
490 operator<<(Os& lhs,
491 const typename ::boost::type_erasure::derived<Base>::type& rhs)
492 {
493 ::boost::type_erasure::call(ostreamable<Os, T>(), lhs, rhs);
494 return lhs;
495 }
496 };
497
498 /// \endcond
499
500 /**
501 * The @ref istreamable concept allows an @ref any to be
502 * read from a @c std::istream.
503 */
504 template<class Is = std::istream, class T = _self>
505 struct istreamable
506 {
507 static void apply(Is& out, T& arg) { out >> arg; }
508 };
509
510 /// \cond show_operators
511
512
513 template<class Base, class Is, class T>
514 struct concept_interface<istreamable<Is, T>, Base, Is> : Base
515 {
516 friend typename detail::non_const_this_param<Base>::type&
517 operator>>(typename detail::non_const_this_param<Base>::type& lhs,
518 typename ::boost::type_erasure::as_param<Base, T&>::type rhs)
519 {
520 ::boost::type_erasure::call(istreamable<Is, T>(), lhs, rhs);
521 return lhs;
522 }
523 };
524
525 template<class Base, class Is, class T>
526 struct concept_interface<
527 istreamable<Is, T>,
528 Base,
529 T,
530 typename ::boost::disable_if< ::boost::type_erasure::is_placeholder<Is> >::type
531 > : Base
532 {
533 friend Is&
534 operator>>(Is& lhs,
535 typename ::boost::type_erasure::derived<Base>::type& rhs)
536 {
537 ::boost::type_erasure::call(istreamable<Is, T>(), lhs, rhs);
538 return lhs;
539 }
540 };
541
542 /// \endcond
543
544 }
545 }
546
547 #endif