• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 /** 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  */
88 BOOST_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  */
94 BOOST_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  */
119 BOOST_TYPE_ERASURE_UNARY_OPERATOR(complementable, ~)
120 /**
121  * The @ref negatable concept allow use of the unary
122  * minus operator on an @ref any.
123  */
124 BOOST_TYPE_ERASURE_UNARY_OPERATOR(negatable, -)
125 
126 #undef BOOST_TYPE_ERASURE_UNARY_OPERATOR
127 
128 template<class R, class T = _self>
129 struct dereferenceable
130 {
applyboost::type_erasure::dereferenceable131     static R apply(const T& arg) { return *arg; }
132 };
133 
134 /// \cond show_operators
135 
136 template<class R, class T, class Base>
137 struct concept_interface<dereferenceable<R, T>, Base, T> : Base
138 {
operator *boost::type_erasure::concept_interface139     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 
183 BOOST_TYPE_ERASURE_BINARY_OPERATOR(addable, +)
184 BOOST_TYPE_ERASURE_BINARY_OPERATOR(subtractable, -)
185 BOOST_TYPE_ERASURE_BINARY_OPERATOR(multipliable, *)
186 BOOST_TYPE_ERASURE_BINARY_OPERATOR(dividable, /)
187 BOOST_TYPE_ERASURE_BINARY_OPERATOR(modable, %)
188 BOOST_TYPE_ERASURE_BINARY_OPERATOR(left_shiftable, <<)
189 BOOST_TYPE_ERASURE_BINARY_OPERATOR(right_shiftable, >>)
190 BOOST_TYPE_ERASURE_BINARY_OPERATOR(bitandable, &)
191 BOOST_TYPE_ERASURE_BINARY_OPERATOR(bitorable, |)
192 BOOST_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 
240 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(add_assignable, +=)
241 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(subtract_assignable, -=)
242 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(multiply_assignable, *=)
243 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(divide_assignable, /=)
244 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(mod_assignable, %=)
245 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(left_shift_assignable, <<=)
246 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(right_shift_assignable, >>=)
247 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(bitand_assignable, &=)
248 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(bitor_assignable, |=)
249 BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(bitxor_assignable, ^=)
250 
251 #undef BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR
252 
253 template<class T = _self, class U = T>
254 struct equality_comparable
255 {
applyboost::type_erasure::equality_comparable256     static bool apply(const T& lhs, const U& rhs) { return lhs == rhs; }
257 };
258 
259 /// \cond show_operators
260 
261 template<class T, class U, class Base>
262 struct concept_interface<equality_comparable<T, U>, Base, T> : Base
263 {
operator ==(const typename derived<Base>::type & lhs,typename as_param<Base,const U &>::type rhs)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     }
operator !=(const typename derived<Base>::type & lhs,typename as_param<Base,const U &>::type rhs)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 
280 template<class T, class U, class Base>
281 struct 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 {
operator ==(const T & lhs,const typename derived<Base>::type & rhs)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     }
operator !=(const T & lhs,const typename derived<Base>::type & rhs)292     friend bool operator!=(const T& lhs, const typename derived<Base>::type& rhs)
293     {
294         return !(lhs == rhs);
295     }
296 };
297 
298 /// \endcond
299 
300 template<class T = _self, class U = T>
301 struct less_than_comparable
302 {
applyboost::type_erasure::less_than_comparable303     static bool apply(const T& lhs, const U& rhs) { return lhs < rhs; }
304 };
305 
306 namespace detail {
307 
308 template<class F, class T, class U>
less_impl(const F & f,const T & lhs,const U & rhs,::boost::mpl::true_)309 bool 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 
324 template<class F, class T, class U>
less_impl(const F & f,const T & lhs,const U & rhs,::boost::mpl::false_)325 bool 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 
334 template<class T, class Base>
335 struct concept_interface<less_than_comparable<T, T>, Base, T> : Base
336 {
operator <(const typename derived<Base>::type & lhs,typename as_param<Base,const T &>::type rhs)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     }
operator >=(const typename derived<Base>::type & lhs,typename as_param<Base,const T &>::type rhs)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     }
operator >(typename as_param<Base,const T &>::type lhs,const typename derived<Base>::type & rhs)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     }
operator <=(typename as_param<Base,const T &>::type lhs,const typename derived<Base>::type & rhs)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 
363 template<class T, class U, class Base>
364 struct concept_interface<less_than_comparable<T, U>, Base, T> : Base
365 {
operator <(const typename derived<Base>::type & lhs,typename as_param<Base,const U &>::type rhs)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     }
operator >=(const typename derived<Base>::type & lhs,typename as_param<Base,const U &>::type rhs)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     }
operator >(typename as_param<Base,const U &>::type lhs,const typename derived<Base>::type & rhs)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     }
operator <=(typename as_param<Base,const U &>::type lhs,const typename derived<Base>::type & rhs)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 
388 template<class T, class U, class Base>
389 struct 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 {
operator <(const T & lhs,const typename derived<Base>::type & rhs)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     }
operator >=(const T & lhs,const typename derived<Base>::type & rhs)400     friend bool operator>=(const T& lhs, const typename derived<Base>::type& rhs)
401     {
402         return !(lhs < rhs);
403     }
operator >(const typename derived<Base>::type & lhs,const T & rhs)404     friend bool operator>(const typename derived<Base>::type& lhs, const T& rhs)
405     {
406         return rhs < lhs;
407     }
operator <=(const typename derived<Base>::type & lhs,const T & rhs)408     friend bool operator<=(const typename derived<Base>::type& lhs, const T& rhs)
409     {
410         return !(rhs < lhs);
411     }
412 };
413 
414 /// \endcond
415 
416 template<class R, class T = _self, class N = std::ptrdiff_t>
417 struct subscriptable
418 {
applyboost::type_erasure::subscriptable419     static R apply(T& arg, const N& index) { return arg[index]; }
420 };
421 
422 /// \cond show_operators
423 
424 template<class R, class T, class N, class Base>
425 struct 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 {
operator []boost::type_erasure::concept_interface431     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 
438 template<class R, class T, class N, class Base>
439 struct 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 {
operator []boost::type_erasure::concept_interface445     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  */
458 template<class Os = std::ostream, class T = _self>
459 struct ostreamable
460 {
applyboost::type_erasure::ostreamable461     static void apply(Os& out, const T& arg) { out << arg; }
462 };
463 
464 /// \cond show_operators
465 
466 template<class Base, class Os, class T>
467 struct concept_interface<ostreamable<Os, T>, Base, Os> : Base
468 {
469     friend typename detail::non_const_this_param<Base>::type&
operator <<(typename detail::non_const_this_param<Base>::type & lhs,typename::boost::type_erasure::as_param<Base,const T &>::type rhs)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 
478 template<class Base, class Os, class T>
479 struct 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&
operator <<(Os & lhs,const typename::boost::type_erasure::derived<Base>::type & rhs)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  */
501 template<class Is = std::istream, class T = _self>
502 struct istreamable
503 {
applyboost::type_erasure::istreamable504     static void apply(Is& out, T& arg) { out >> arg; }
505 };
506 
507 /// \cond show_operators
508 
509 
510 template<class Base, class Is, class T>
511 struct concept_interface<istreamable<Is, T>, Base, Is> : Base
512 {
513     friend typename detail::non_const_this_param<Base>::type&
operator >>(typename detail::non_const_this_param<Base>::type & lhs,typename::boost::type_erasure::as_param<Base,T &>::type rhs)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 
522 template<class Base, class Is, class T>
523 struct 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&
operator >>(Is & lhs,typename::boost::type_erasure::derived<Base>::type & rhs)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