// Boost.TypeErasure library // // Copyright 2011 Steven Watanabe // // Distributed under the Boost Software License Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // $Id$ #ifndef BOOST_TYPE_ERASURE_OPERATORS_HPP_INCLUDED #define BOOST_TYPE_ERASURE_OPERATORS_HPP_INCLUDED #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace type_erasure { template class any; /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_UNARY_INPLACE_OPERATOR(name, op) \ template \ struct name \ { \ static void apply(T& arg) { op arg; } \ }; \ \ template \ struct concept_interface, Base, T, \ typename ::boost::enable_if< \ detail::should_be_non_const \ >::type \ > : Base \ { \ typedef typename ::boost::type_erasure::derived::type _derived; \ _derived& operator op() \ { \ ::boost::type_erasure::call(name(), *this); \ return static_cast<_derived&>(*this); \ } \ typename ::boost::type_erasure::rebind_any::type operator op(int) \ { \ typename ::boost::type_erasure::rebind_any::type result( \ static_cast<_derived&>(*this)); \ ::boost::type_erasure::call(name(), *this); \ return result; \ } \ }; \ \ template \ struct concept_interface, Base, T, \ typename ::boost::enable_if< \ detail::should_be_const \ >::type \ > : Base \ { \ typedef typename ::boost::type_erasure::derived::type _derived; \ const _derived& operator op() const \ { \ ::boost::type_erasure::call(name(), *this); \ return static_cast(*this); \ } \ typename ::boost::type_erasure::rebind_any::type operator op(int) const \ { \ typename ::boost::type_erasure::rebind_any::type result( \ static_cast(*this)); \ ::boost::type_erasure::call(name(), *this); \ return result; \ } \ }; /** * The @ref incrementable concept allow pre and * post increment on an @ref any. The contained * type must provide a pre-increment operator. */ BOOST_TYPE_ERASURE_UNARY_INPLACE_OPERATOR(incrementable, ++) /** * The @ref decrementable concept allow pre and * post decrement on an @ref any. The contained * type must provide a pre-decrement operator. */ BOOST_TYPE_ERASURE_UNARY_INPLACE_OPERATOR(decrementable, --) #undef BOOST_TYPE_ERASURE_UNARY_INPLACE_OPERATOR /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_UNARY_OPERATOR(name, op) \ template \ struct name \ { \ static R apply(const T& arg) { return op arg; } \ }; \ \ template \ struct concept_interface, Base, T> : Base \ { \ typename ::boost::type_erasure::rebind_any::type operator op() const \ { \ return ::boost::type_erasure::call(name(), *this); \ } \ }; /** * The @ref complementable concept allow use of the bitwise * complement operator on an @ref any. */ BOOST_TYPE_ERASURE_UNARY_OPERATOR(complementable, ~) /** * The @ref negatable concept allow use of the unary * minus operator on an @ref any. */ BOOST_TYPE_ERASURE_UNARY_OPERATOR(negatable, -) #undef BOOST_TYPE_ERASURE_UNARY_OPERATOR template struct dereferenceable { static R apply(const T& arg) { return *arg; } }; /// \cond show_operators template struct concept_interface, Base, T> : Base { typename ::boost::type_erasure::rebind_any::type operator*() const { return ::boost::type_erasure::call(dereferenceable(), *this); } }; /// \endcond /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_BINARY_OPERATOR(name, op) \ template \ struct name \ { \ static R apply(const T& lhs, const U& rhs) { return lhs op rhs; } \ }; \ \ template \ struct concept_interface, Base, T> : Base \ { \ friend typename rebind_any::type \ operator op(const typename derived::type& lhs, \ typename as_param::type rhs) \ { \ return ::boost::type_erasure::call(name(), lhs, rhs); \ } \ }; \ \ template \ struct concept_interface< \ name, \ Base, \ U, \ typename ::boost::disable_if< \ ::boost::type_erasure::is_placeholder >::type \ > : Base \ { \ friend typename rebind_any::type \ operator op(const T& lhs, \ const typename derived::type& rhs) \ { \ return ::boost::type_erasure::call(name(), lhs, rhs); \ } \ }; BOOST_TYPE_ERASURE_BINARY_OPERATOR(addable, +) BOOST_TYPE_ERASURE_BINARY_OPERATOR(subtractable, -) BOOST_TYPE_ERASURE_BINARY_OPERATOR(multipliable, *) BOOST_TYPE_ERASURE_BINARY_OPERATOR(dividable, /) BOOST_TYPE_ERASURE_BINARY_OPERATOR(modable, %) BOOST_TYPE_ERASURE_BINARY_OPERATOR(left_shiftable, <<) BOOST_TYPE_ERASURE_BINARY_OPERATOR(right_shiftable, >>) BOOST_TYPE_ERASURE_BINARY_OPERATOR(bitandable, &) BOOST_TYPE_ERASURE_BINARY_OPERATOR(bitorable, |) BOOST_TYPE_ERASURE_BINARY_OPERATOR(bitxorable, ^) #undef BOOST_TYPE_ERASURE_BINARY_OPERATOR /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(name, op) \ template \ struct name \ { \ static void apply(T& lhs, const U& rhs) { lhs op rhs; } \ }; \ \ template \ struct concept_interface, Base, T, \ typename ::boost::disable_if< \ ::boost::is_same< \ typename ::boost::type_erasure::placeholder_of::type, \ const T& \ > \ >::type \ > : Base \ { \ friend typename detail::non_const_this_param::type& \ operator op(typename detail::non_const_this_param::type& lhs, \ typename as_param::type rhs) \ { \ ::boost::type_erasure::call(name(),lhs, rhs); \ return lhs; \ } \ }; \ \ template \ struct concept_interface< \ name, \ Base, \ U, \ typename ::boost::disable_if< \ ::boost::type_erasure::is_placeholder >::type \ > : Base \ { \ friend T& \ operator op(T& lhs, const typename derived::type& rhs) \ { \ ::boost::type_erasure::call(name(),lhs, rhs); \ return lhs; \ } \ }; BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(add_assignable, +=) BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(subtract_assignable, -=) BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(multiply_assignable, *=) BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(divide_assignable, /=) BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(mod_assignable, %=) BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(left_shift_assignable, <<=) BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(right_shift_assignable, >>=) BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(bitand_assignable, &=) BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(bitor_assignable, |=) BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(bitxor_assignable, ^=) #undef BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR template struct equality_comparable { static bool apply(const T& lhs, const U& rhs) { return lhs == rhs; } }; /// \cond show_operators template struct concept_interface, Base, T> : Base { friend bool operator==(const typename derived::type& lhs, typename as_param::type rhs) { if(::boost::type_erasure::check_match(equality_comparable(), lhs, rhs)) { return ::boost::type_erasure::unchecked_call(equality_comparable(), lhs, rhs); } else { return false; } } friend bool operator!=(const typename derived::type& lhs, typename as_param::type rhs) { return !(lhs == rhs); } }; template struct concept_interface< equality_comparable, Base, U, typename ::boost::disable_if< ::boost::type_erasure::is_placeholder >::type > : Base { friend bool operator==(const T& lhs, const typename derived::type& rhs) { return ::boost::type_erasure::call(equality_comparable(), lhs, rhs); } friend bool operator!=(const T& lhs, const typename derived::type& rhs) { return !(lhs == rhs); } }; /// \endcond template struct less_than_comparable { static bool apply(const T& lhs, const U& rhs) { return lhs < rhs; } }; namespace detail { template bool less_impl(const F& f, const T& lhs, const U& rhs, ::boost::mpl::true_) { if(::boost::type_erasure::check_match(f, lhs, rhs)) { return ::boost::type_erasure::unchecked_call(f, lhs, rhs); } else { return ::boost::type_erasure::typeid_of( static_cast::type&>(lhs) ).before( ::boost::type_erasure::typeid_of( static_cast::type&>(rhs) ) ) != false; } } template bool less_impl(const F& f, const T& lhs, const U& rhs, ::boost::mpl::false_) { return ::boost::type_erasure::call(f, lhs, rhs); } } /// \cond show_operators template struct concept_interface, Base, T> : Base { friend bool operator<(const typename derived::type& lhs, typename as_param::type rhs) { return ::boost::type_erasure::detail::less_impl( less_than_comparable(), lhs, rhs, ::boost::type_erasure::is_relaxed< typename ::boost::type_erasure::concept_of::type>()); } friend bool operator>=(const typename derived::type& lhs, typename as_param::type rhs) { return !(lhs < rhs); } friend bool operator>(typename as_param::type lhs, const typename derived::type& rhs) { return rhs < lhs; } friend bool operator<=(typename as_param::type lhs, const typename derived::type& rhs) { return !(rhs < lhs); } }; template struct concept_interface, Base, T> : Base { friend bool operator<(const typename derived::type& lhs, typename as_param::type rhs) { return ::boost::type_erasure::call(less_than_comparable(), lhs, rhs); } friend bool operator>=(const typename derived::type& lhs, typename as_param::type rhs) { return !(lhs < rhs); } friend bool operator>(typename as_param::type lhs, const typename derived::type& rhs) { return rhs < lhs; } friend bool operator<=(typename as_param::type lhs, const typename derived::type& rhs) { return !(rhs < lhs); } }; template struct concept_interface< less_than_comparable, Base, U, typename ::boost::disable_if< ::boost::type_erasure::is_placeholder >::type > : Base { friend bool operator<(const T& lhs, const typename derived::type& rhs) { return ::boost::type_erasure::call(less_than_comparable(), lhs, rhs); } friend bool operator>=(const T& lhs, const typename derived::type& rhs) { return !(lhs < rhs); } friend bool operator>(const typename derived::type& lhs, const T& rhs) { return rhs < lhs; } friend bool operator<=(const typename derived::type& lhs, const T& rhs) { return !(rhs < lhs); } }; /// \endcond template struct subscriptable { static R apply(T& arg, const N& index) { return arg[index]; } }; /// \cond show_operators template struct concept_interface, Base, typename ::boost::remove_const::type, typename ::boost::enable_if< ::boost::type_erasure::detail::should_be_non_const >::type > : Base { typename ::boost::type_erasure::rebind_any::type operator[]( typename ::boost::type_erasure::as_param::type index) { return ::boost::type_erasure::call(subscriptable(), *this, index); } }; template struct concept_interface, Base, typename ::boost::remove_const::type, typename ::boost::enable_if< ::boost::type_erasure::detail::should_be_const >::type > : Base { typename ::boost::type_erasure::rebind_any::type operator[]( typename ::boost::type_erasure::as_param::type index) const { return ::boost::type_erasure::call(subscriptable(), *this, index); } }; /// \endcond /** * The @ref ostreamable concept allows an @ref any to be * written to a @c std::ostream. */ template struct ostreamable { static void apply(Os& out, const T& arg) { out << arg; } }; /// \cond show_operators template struct concept_interface, Base, Os> : Base { friend typename detail::non_const_this_param::type& operator<<(typename detail::non_const_this_param::type& lhs, typename ::boost::type_erasure::as_param::type rhs) { ::boost::type_erasure::call(ostreamable(), lhs, rhs); return lhs; } }; template struct concept_interface< ostreamable, Base, T, typename ::boost::disable_if< ::boost::type_erasure::is_placeholder >::type > : Base { friend Os& operator<<(Os& lhs, const typename ::boost::type_erasure::derived::type& rhs) { ::boost::type_erasure::call(ostreamable(), lhs, rhs); return lhs; } }; /// \endcond /** * The @ref istreamable concept allows an @ref any to be * read from a @c std::istream. */ template struct istreamable { static void apply(Is& out, T& arg) { out >> arg; } }; /// \cond show_operators template struct concept_interface, Base, Is> : Base { friend typename detail::non_const_this_param::type& operator>>(typename detail::non_const_this_param::type& lhs, typename ::boost::type_erasure::as_param::type rhs) { ::boost::type_erasure::call(istreamable(), lhs, rhs); return lhs; } }; template struct concept_interface< istreamable, Base, T, typename ::boost::disable_if< ::boost::type_erasure::is_placeholder >::type > : Base { friend Is& operator>>(Is& lhs, typename ::boost::type_erasure::derived::type& rhs) { ::boost::type_erasure::call(istreamable(), lhs, rhs); return lhs; } }; /// \endcond } } #endif