// See http://www.boost.org/libs/any for Documentation. #ifndef BOOST_PROPOSAL_ANY_INCLUDED #define BOOST_PROPOSAL_ANY_INCLUDED // This is a proposal for a new version of boost::any // It increases performance and does not depend on rtti // tested with // - vc++ 2010 express // - gcc 4.5 // author: Martin Bidlingmaier // original version contributed by Kevlin Henney and Ed Brey, Mark Rodgers, Peter Dimov, James Curran #include "boost/config.hpp" #include #include #include #include #include #include #include #include #include namespace boost { namespace proposal { namespace detail { namespace any_detail { //wrapper_base and wrapper are used for type erasure class wrapper_base { public: virtual ~wrapper_base() { } virtual wrapper_base *copy() = 0; #ifndef BOOST_NO_TYPEID virtual const std::type_info &get_type_info() const = 0; #endif }; template< class T > class wrapper : public wrapper_base { public: T obj; wrapper( const T &object ) : obj( object ) { } #if defined( BOOST_HAS_RVALUE_REFS ) && !defined( BOOST_MSVC ) wrapper( T &&object ) : obj( std::move( object ) ) { } #endif wrapper_base *copy() { return new wrapper< T >( obj ); } #ifndef BOOST_NO_TYPEID virtual const std::type_info &get_type_info() const { return typeid( T ); } #endif }; //remove all references, const and volatile template< class T > class remove_rcv { private: typedef BOOST_DEDUCED_TYPENAME remove_reference< T >::type no_ref; typedef BOOST_DEDUCED_TYPENAME remove_cv< no_ref >::type no_ref_no_const_no_volatile; public: typedef no_ref_no_const_no_volatile type; }; } } class any { public: any() { id = 0; content = 0; } #if defined( BOOST_HAS_RVALUE_REFS ) && !defined( BOOST_MSVC ) any( const any &other_any ) { id = other_any.id; if( other_any.content ) content = other_any.content->copy(); else content = 0; } any( any &&other_any ) { id = other_any.id; content = other_any.content; other_any.content = 0; } template< class T > any( T &&object , BOOST_DEDUCED_TYPENAME disable_if < is_same < BOOST_DEDUCED_TYPENAME detail::any_detail::remove_rcv< T >::type , any > >::type * = 0 //disable this overload, for T = any (or T = const any &, ...) ) { //this constructor handles copy construction, move construction and construction from T typedef BOOST_DEDUCED_TYPENAME detail::any_detail::remove_rcv< T >::type actual_type; id = typeid(actual_type).name(); content = new detail::any_detail::wrapper< actual_type >( std::forward< T >( object ) ); } #else any( const any &other_any ) { id = other_any.id; if( other_any.content ) content = other_any.content->copy(); else content = 0; } template< class T > any( const T &object ) { id = typeid(T).name(); content = new detail::any_detail::wrapper< T >( object ); } #endif ~any() { delete content; } any &swap( any &other_any ) { std::swap( id , other_any.id ); std::swap( content , other_any.content ); return *this; } #if defined( BOOST_HAS_RVALUE_REFS ) && !defined( BOOST_MSVC ) template< class T > any &operator=( T &&object ) { //this function handles all assignments any( std::forward< T >( object ) ).swap( *this ); return *this; } #else any &operator=( const any &other_any ) { any( other_any ).swap( *this ); return *this; } template< class T > any &operator=( const T &object ) { any( object ).swap( *this ); return *this; } #endif bool empty() const { return ( content == 0 ); } #ifndef BOOST_NO_TYPEID const std::type_info &type() const { if( content ) return content->get_type_info(); else return typeid( void ); } #endif //new member to query type without rtti: template< class T > bool is_type() //alternative: has_type() { typedef BOOST_DEDUCED_TYPENAME detail::any_detail::remove_rcv< T >::type actual_type; return ( id == typeid(actual_type).name() ); } //specialization for T=void in namespace scope #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS template< class T > friend T *any_cast( any * ); template< class T > friend T &any_cast( any & ); template< class T > friend T *unsafe_any_cast( any * ); private: #else public: #endif const char * id; //id of the type in content type or 0, if content == 0 detail::any_detail::wrapper_base *content; }; class bad_any_cast : public std::bad_cast { public: virtual const char *what() const throw() { return "boost::bad_any_cast: " "failed conversion using boost::any_cast"; } }; template< class T > T *any_cast( any *any_ptr ) { typedef BOOST_DEDUCED_TYPENAME detail::any_detail::remove_rcv< T >::type actual_type; if( typeid(actual_type).name() == any_ptr->id ) return &static_cast< detail::any_detail::wrapper< actual_type >* >( any_ptr->content )->obj; else return 0; } template< class T > const T *any_cast( const any *any_ptr ) { return any_cast< T >( const_cast< any* >( any_ptr ) ); } template< class T > T &any_cast( any &any_ref ) { typedef BOOST_DEDUCED_TYPENAME detail::any_detail::remove_rcv< T >::type actual_type; if( typeid(actual_type).name() == any_ref.id ) return static_cast< detail::any_detail::wrapper< actual_type >* >( any_ref.content )->obj; else throw_exception( bad_any_cast() ); } template< class T > const T &any_cast( const any &any_ref ) { return any_cast< T >( const_cast< any& >( any_ref ) ); } template< class T > T *unsafe_any_cast( any *any_ptr ) { return &static_cast< detail::any_detail::wrapper< T >* >( any_ptr->content )->obj; } template< class T > const T*unsafe_any_cast( const any *any_ptr ) { return unsafe_any_cast< T >( const_cast< any* >( any_ptr ) ); } } } //provide a specialization of std::swap for boost::any namespace std { template<> void swap( boost::proposal::any &first , boost::proposal::any &second ) { first.swap( second ); } } // Copyright Martin Bidlingmaier 2011 // 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) #endif