// 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_ANY_CAST_HPP_INCLUDED #define BOOST_TYPE_ERASURE_ANY_CAST_HPP_INCLUDED #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace type_erasure { namespace detail { template void* get_pointer(::boost::type_erasure::any& arg) { return ::boost::type_erasure::detail::access::data(arg).data; } template const void* get_pointer(const ::boost::type_erasure::any& arg) { return ::boost::type_erasure::detail::access::data(arg).data; } template void* get_pointer(::boost::type_erasure::any& arg) { return ::boost::type_erasure::detail::access::data(arg).data; } template void* get_pointer(const ::boost::type_erasure::any& arg) { return ::boost::type_erasure::detail::access::data(arg).data; } template const void* get_pointer(::boost::type_erasure::any& arg) { return ::boost::type_erasure::detail::access::data(arg).data; } template const void* get_pointer(const ::boost::type_erasure::any& arg) { return ::boost::type_erasure::detail::access::data(arg).data; } template bool check_any_cast(const any&, ::boost::mpl::true_) { return true; } template bool check_any_cast(const any& arg, ::boost::mpl::false_) { typedef typename ::boost::remove_cv< typename ::boost::remove_reference::type >::type tag_type; return ::boost::type_erasure::detail::access::table(arg) .template find >()() == typeid(T); } template bool check_any_cast(const any& arg) { return ::boost::type_erasure::detail::check_any_cast( arg, ::boost::is_void::type>()); } } /** * Attempts to extract the object that @c arg holds. * If casting to a pointer fails, \any_cast returns * a null pointer. Casting to @c void* always succeeds * and returns the address of stored object. * * \code * any, copy_constructible<> > > x(1); * any_cast(x); // returns 1 * any_cast(x); // returns a reference to the contents of x * any_cast(x); // throws bad_any_cast * any_cast(&x); // returns a pointer to the contents of x * any_cast(&x); // returns a pointer to the contents of x * any_cast(&x); // returns NULL * \endcode * * \pre if @c arg is a pointer, @c T must be a pointer type. * \pre @c Concept must contain @ref typeid_<Tag>. * * \throws bad_any_cast if @c arg doesn't contain * an object of type @c T and we're casting * to a value or reference. */ template T any_cast(any& arg) { if(::boost::type_erasure::detail::check_any_cast(arg)) { return *static_cast< typename ::boost::remove_reference< typename ::boost::add_const::type >::type* >(::boost::type_erasure::detail::get_pointer(arg)); } else { BOOST_THROW_EXCEPTION(::boost::type_erasure::bad_any_cast()); } } /** \overload */ template T any_cast(const any& arg) { if(::boost::type_erasure::detail::check_any_cast(arg)) { return *static_cast< typename ::boost::remove_reference< typename ::boost::add_const::type >::type* >(::boost::type_erasure::detail::get_pointer(arg)); } else { BOOST_THROW_EXCEPTION(::boost::type_erasure::bad_any_cast()); } } /** \overload */ template T any_cast(any* arg) { BOOST_MPL_ASSERT((::boost::is_pointer)); if(::boost::type_erasure::detail::check_any_cast< typename ::boost::remove_pointer::type>(*arg)) { return static_cast< typename ::boost::remove_pointer::type*>( ::boost::type_erasure::detail::get_pointer(*arg)); } else { return 0; } } /** \overload */ template T any_cast(const any* arg) { BOOST_MPL_ASSERT((::boost::is_pointer)); if(::boost::type_erasure::detail::check_any_cast< typename ::boost::remove_pointer::type>(*arg)) { return static_cast< typename ::boost::remove_pointer::type*>( ::boost::type_erasure::detail::get_pointer(*arg)); } else { return 0; } } } } #endif