diff options
author | DongHun Kwak <dh0128.kwak@samsung.com> | 2016-10-06 10:33:54 +0900 |
---|---|---|
committer | DongHun Kwak <dh0128.kwak@samsung.com> | 2016-10-06 10:36:09 +0900 |
commit | d9ec475d945d3035377a0d89ed42e382d8988891 (patch) | |
tree | 34aff2cee4b209906243ab5499d61f3edee2982f /boost/type_erasure/dynamic_any_cast.hpp | |
parent | 71d216b90256936a9638f325af9bc69d720e75de (diff) | |
download | boost-d9ec475d945d3035377a0d89ed42e382d8988891.tar.gz boost-d9ec475d945d3035377a0d89ed42e382d8988891.tar.bz2 boost-d9ec475d945d3035377a0d89ed42e382d8988891.zip |
Imported Upstream version 1.60.0
Change-Id: Ie709530d6d5841088ceaba025cbe175a4ef43050
Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
Diffstat (limited to 'boost/type_erasure/dynamic_any_cast.hpp')
-rw-r--r-- | boost/type_erasure/dynamic_any_cast.hpp | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/boost/type_erasure/dynamic_any_cast.hpp b/boost/type_erasure/dynamic_any_cast.hpp new file mode 100644 index 0000000000..01aa2b6ef9 --- /dev/null +++ b/boost/type_erasure/dynamic_any_cast.hpp @@ -0,0 +1,234 @@ +// 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 <boost/type_erasure/detail/normalize.hpp> +#include <boost/type_erasure/binding_of.hpp> +#include <boost/type_erasure/static_binding.hpp> +#include <boost/type_erasure/dynamic_binding.hpp> +#include <boost/type_erasure/concept_of.hpp> +#include <boost/type_erasure/placeholder_of.hpp> +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/binding.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/mpl/set.hpp> +#include <boost/mpl/fold.hpp> +#include <boost/type_traits/add_const.hpp> +#include <boost/type_traits/add_reference.hpp> +#include <boost/type_traits/remove_const.hpp> +#include <boost/type_traits/remove_reference.hpp> + +namespace boost { +namespace type_erasure { + +namespace detail { + +template<class P, class P2, class Any> +struct make_ref_placeholder; + +template<class P, class P2, class Any> +struct make_ref_placeholder<P, P2, const Any&> { typedef const P& type; }; +template<class P, class P2, class Any> +struct make_ref_placeholder<P, P2, Any&> { typedef P& type; }; +template<class P, class P2, class Any> +struct make_ref_placeholder<P, P2&, const Any&> { typedef P& type; }; +template<class P, class P2, class Any> +struct make_ref_placeholder<P, P2&, Any&> { typedef P& type; }; +template<class P, class P2, class Any> +struct make_ref_placeholder<P, const P2&, const Any&> { typedef const P& type; }; +template<class P, class P2, class Any> +struct make_ref_placeholder<P, const P2&, Any&> { typedef const P& type; }; + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +template<class P, class P2, class Any> +struct make_ref_placeholder { typedef P&& type; }; +template<class P, class P2, class Any> +struct make_ref_placeholder<P, P2&, Any> { typedef P& type; }; +template<class P, class P2, class Any> +struct make_ref_placeholder<P, const P2&, Any> { typedef const P& type; }; +template<class P, class P2, class Any> +struct make_ref_placeholder<P, P2&&, Any> { typedef P&& type; }; +template<class P, class P2, class Any> +struct make_ref_placeholder<P, P2&&, const Any&> { typedef const P& type; }; +template<class P, class P2, class Any> +struct make_ref_placeholder<P, P2&&, Any&> { typedef P& type; }; +#endif + +template<class R, class Tag> +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<R>::type + >::type + >::type, + typename ::boost::remove_const< + typename ::boost::remove_reference< + Tag + >::type + >::type + > + > type; +}; + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +template<class R, class Any, class Map> +R dynamic_any_cast_impl(Any&& arg, const static_binding<Map>& map) +#else +template<class R, class Any, class Map> +R dynamic_any_cast_impl(Any& arg, const static_binding<Map>& map) +#endif +{ + typedef typename ::boost::remove_const<typename ::boost::remove_reference<Any>::type>::type src_type; + typedef typename ::boost::type_erasure::detail::normalize_concept< + typename ::boost::type_erasure::concept_of<src_type>::type + >::type normalized; + typedef typename ::boost::mpl::fold< + normalized, + ::boost::mpl::set0<>, + ::boost::type_erasure::detail::get_placeholders< + ::boost::mpl::_2, + ::boost::mpl::_1 + > + >::type placeholders; + typedef ::boost::type_erasure::detail::substitution_map< ::boost::mpl::map0<> > identity_map; + ::boost::type_erasure::dynamic_binding<placeholders> my_binding( + ::boost::type_erasure::binding_of(arg), + ::boost::type_erasure::make_binding<identity_map>()); + typedef typename ::boost::remove_const< + typename ::boost::remove_reference< + typename ::boost::type_erasure::placeholder_of<R>::type + >::type + >::type result_placeholder; + ::boost::type_erasure::binding< typename ::boost::type_erasure::concept_of<R>::type> new_binding( + my_binding, + map); + typedef ::boost::type_erasure::any< + typename ::boost::type_erasure::concept_of<R>::type, + typename ::boost::type_erasure::detail::make_ref_placeholder< + result_placeholder, + typename ::boost::type_erasure::placeholder_of<src_type>::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<Any>(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 + * @ref register_binding. + * + * Example: + * \code + * // Assume that typeid_<>, copy_constructible<>, and incrementable<> + * // have all been registered for int. + * any<mpl::vector<typeid_<>, copy_constructible<> > > x(1); + * typedef any< + * mpl::vector< + * typeid_<>, + * copy_constructible<>, + * incrementable<> + * > + * > incrementable_any; + * auto y = dynamic_any_cast<incrementable_any>(x); + * ++y; + * assert(any_cast<int>(y) == 2); + * \endcode + */ +template<class R, class Any> +R dynamic_any_cast(Any&& arg); + +/** + * \overload + */ +template<class R, class Any, class Map> +R dynamic_any_cast(Any&& arg, const static_binding<Map>&); + +#else + +template<class R, class Concept, class Tag> +R dynamic_any_cast(const any<Concept, Tag>& arg) +{ + return ::boost::type_erasure::detail::dynamic_any_cast_impl<R>(arg, + ::boost::type_erasure::make_binding<typename ::boost::type_erasure::detail::make_result_placeholder_map<R, Tag>::type>()); +} + +template<class R, class Concept, class Tag> +R dynamic_any_cast(any<Concept, Tag>& arg) +{ + return ::boost::type_erasure::detail::dynamic_any_cast_impl<R>(arg, + ::boost::type_erasure::make_binding<typename ::boost::type_erasure::detail::make_result_placeholder_map<R, Tag>::type>()); +} + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +template<class R, class Concept, class Tag> +R dynamic_any_cast(any<Concept, Tag>&& arg) +{ + return ::boost::type_erasure::detail::dynamic_any_cast_impl<R>(::std::move(arg), + ::boost::type_erasure::make_binding<typename ::boost::type_erasure::detail::make_result_placeholder_map<R, Tag>::type>()); +} +#endif + +template<class R, class Concept, class Tag, class Map> +R dynamic_any_cast(const any<Concept, Tag>& arg, const static_binding<Map>& map) +{ + return ::boost::type_erasure::detail::dynamic_any_cast_impl<R>(arg, map); +} + +template<class R, class Concept, class Tag, class Map> +R dynamic_any_cast(any<Concept, Tag>& arg, const static_binding<Map>& map) +{ + return ::boost::type_erasure::detail::dynamic_any_cast_impl<R>(arg, map); +} + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +template<class R, class Concept, class Tag, class Map> +R dynamic_any_cast(any<Concept, Tag>&& arg, const static_binding<Map>& map) +{ + return ::boost::type_erasure::detail::dynamic_any_cast_impl<R>(::std::move(arg), map); +} +#endif + +#endif + +} +} + +#endif |