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

source code of boost/libs/type_erasure/include/boost/type_erasure/operators.hpp