// Boost.TypeErasure library // // Copyright 2015 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_DYNAMIC_ANY_CAST_HPP_INCLUDED #define BOOST_TYPE_ERASURE_DYNAMIC_ANY_CAST_HPP_INCLUDED #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace type_erasure { namespace detail { template struct make_ref_placeholder; template struct make_ref_placeholder { typedef const P& type; }; template struct make_ref_placeholder { typedef P& type; }; template struct make_ref_placeholder { typedef P& type; }; template struct make_ref_placeholder { typedef P& type; }; template struct make_ref_placeholder { typedef const P& type; }; template struct make_ref_placeholder { typedef const P& type; }; #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES template struct make_ref_placeholder { typedef P&& type; }; template struct make_ref_placeholder { typedef P& type; }; template struct make_ref_placeholder { typedef const P& type; }; template struct make_ref_placeholder { typedef P&& type; }; template struct make_ref_placeholder { typedef const P& type; }; template struct make_ref_placeholder { typedef P& type; }; #endif template struct make_result_placeholder_map { typedef ::boost::mpl::map< ::boost::mpl::pair< typename ::boost::remove_const< typename ::boost::remove_reference< typename ::boost::type_erasure::placeholder_of::type >::type >::type, typename ::boost::remove_const< typename ::boost::remove_reference< Tag >::type >::type > > type; }; #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES template R dynamic_any_cast_impl(Any&& arg, const static_binding& map) #else template R dynamic_any_cast_impl(Any& arg, const static_binding& map) #endif { typedef typename ::boost::remove_const::type>::type src_type; typedef typename ::boost::type_erasure::detail::normalize_concept< typename ::boost::type_erasure::concept_of::type >::type normalized; typedef typename ::boost::mpl::fold< normalized, #ifndef BOOST_TYPE_ERASURE_USE_MP11 ::boost::mpl::set0<>, #else ::boost::mp11::mp_list<>, #endif ::boost::type_erasure::detail::get_placeholders< ::boost::mpl::_2, ::boost::mpl::_1 > >::type placeholders; #ifndef BOOST_TYPE_ERASURE_USE_MP11 typedef ::boost::type_erasure::detail::substitution_map< ::boost::mpl::map0<> > identity_map; #else typedef ::boost::type_erasure::detail::make_identity_placeholder_map identity_map; #endif ::boost::type_erasure::dynamic_binding my_binding( ::boost::type_erasure::binding_of(arg), ::boost::type_erasure::make_binding()); typedef typename ::boost::remove_const< typename ::boost::remove_reference< typename ::boost::type_erasure::placeholder_of::type >::type >::type result_placeholder; ::boost::type_erasure::binding< typename ::boost::type_erasure::concept_of::type> new_binding( my_binding, map); typedef ::boost::type_erasure::any< typename ::boost::type_erasure::concept_of::type, typename ::boost::type_erasure::detail::make_ref_placeholder< result_placeholder, typename ::boost::type_erasure::placeholder_of::type, #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Any #else Any& #endif >::type > result_ref_type; #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES return result_ref_type(std::forward(arg), new_binding); #else return result_ref_type(arg, new_binding); #endif } } #ifdef BOOST_TYPE_ERASURE_DOXYGEN /** * Downcasts or crosscasts an @ref any. * * \pre @c R and @c Any must both be specializations of @ref any. * \pre PlaceholderMap must be an MPL map with a key * for every non-deduced placeholder used by R. * The value associated with each key should * be the corresponding placeholder in Any. * \pre The concept of Any must include @ref typeid_, for every * @ref placeholder which is used by R. * * The single argument form can only be used when @c R uses * a single non-deduced placeholder. * * \throws bad_any_cast if the concepts used by R were * not previously registered via a call to * \register_binding. * * Example: * \code * // Assume that typeid_<>, copy_constructible<>, and incrementable<> * // have all been registered for int. * any, copy_constructible<> > > x(1); * typedef any< * mpl::vector< * typeid_<>, * copy_constructible<>, * incrementable<> * > * > incrementable_any; * auto y = dynamic_any_cast(x); * ++y; * assert(any_cast(y) == 2); * \endcode */ template R dynamic_any_cast(Any&& arg); /** * \overload */ template R dynamic_any_cast(Any&& arg, const static_binding&); #else template R dynamic_any_cast(const any& arg) { return ::boost::type_erasure::detail::dynamic_any_cast_impl(arg, ::boost::type_erasure::make_binding::type>()); } template R dynamic_any_cast(any& arg) { return ::boost::type_erasure::detail::dynamic_any_cast_impl(arg, ::boost::type_erasure::make_binding::type>()); } #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES template R dynamic_any_cast(any&& arg) { return ::boost::type_erasure::detail::dynamic_any_cast_impl(::std::move(arg), ::boost::type_erasure::make_binding::type>()); } #endif template R dynamic_any_cast(const any& arg, const static_binding& map) { return ::boost::type_erasure::detail::dynamic_any_cast_impl(arg, map); } template R dynamic_any_cast(any& arg, const static_binding& map) { return ::boost::type_erasure::detail::dynamic_any_cast_impl(arg, map); } #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES template R dynamic_any_cast(any&& arg, const static_binding& map) { return ::boost::type_erasure::detail::dynamic_any_cast_impl(::std::move(arg), map); } #endif #endif } } #endif