diff options
Diffstat (limited to 'boost/any.hpp')
-rw-r--r-- | boost/any.hpp | 183 |
1 files changed, 127 insertions, 56 deletions
diff --git a/boost/any.hpp b/boost/any.hpp index a8c654c373..580b5b4955 100644 --- a/boost/any.hpp +++ b/boost/any.hpp @@ -3,32 +3,32 @@ #ifndef BOOST_ANY_INCLUDED #define BOOST_ANY_INCLUDED +#if defined(_MSC_VER) +# pragma once +#endif + // what: variant type boost::any // who: contributed by Kevlin Henney, // with features contributed and bugs found by -// Ed Brey, Mark Rodgers, Peter Dimov, and James Curran -// when: July 2001 -// where: tested with BCC 5.5, MSVC 6.0, and g++ 2.95 +// Antony Polukhin, Ed Brey, Mark Rodgers, +// Peter Dimov, and James Curran +// when: July 2001, April 2013 - May 2013 #include <algorithm> -#include <typeinfo> #include "boost/config.hpp" +#include <boost/type_index.hpp> #include <boost/type_traits/remove_reference.hpp> +#include <boost/type_traits/decay.hpp> +#include <boost/type_traits/remove_cv.hpp> +#include <boost/type_traits/add_reference.hpp> #include <boost/type_traits/is_reference.hpp> +#include <boost/type_traits/is_const.hpp> #include <boost/throw_exception.hpp> #include <boost/static_assert.hpp> - -// See boost/python/type_id.hpp -// TODO: add BOOST_TYPEID_COMPARE_BY_NAME to config.hpp -# if (defined(__GNUC__) && __GNUC__ >= 3) \ - || defined(_AIX) \ - || ( defined(__sgi) && defined(__host_mips)) \ - || (defined(__hpux) && defined(__HP_aCC)) \ - || (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC)) -# define BOOST_AUX_ANY_TYPE_ID_NAME -#include <cstring> -# endif +#include <boost/utility/enable_if.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/type_traits/is_const.hpp> namespace boost { @@ -36,14 +36,16 @@ namespace boost { public: // structors - any() + any() BOOST_NOEXCEPT : content(0) { } template<typename ValueType> any(const ValueType & value) - : content(new holder<ValueType>(value)) + : content(new holder< + BOOST_DEDUCED_TYPENAME remove_cv<BOOST_DEDUCED_TYPENAME decay<const ValueType>::type>::type + >(value)) { } @@ -52,19 +54,39 @@ namespace boost { } - ~any() +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + // Move constructor + any(any&& other) BOOST_NOEXCEPT + : content(other.content) + { + other.content = 0; + } + + // Perfect forwarding of ValueType + template<typename ValueType> + any(ValueType&& value + , typename boost::disable_if<boost::is_same<any&, ValueType> >::type* = 0 // disable if value has type `any&` + , typename boost::disable_if<boost::is_const<ValueType> >::type* = 0) // disable if value has type `const ValueType&&` + : content(new holder< typename decay<ValueType>::type >(static_cast<ValueType&&>(value))) + { + } +#endif + + ~any() BOOST_NOEXCEPT { delete content; } public: // modifiers - any & swap(any & rhs) + any & swap(any & rhs) BOOST_NOEXCEPT { std::swap(content, rhs.content); return *this; } + +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES template<typename ValueType> any & operator=(const ValueType & rhs) { @@ -74,20 +96,49 @@ namespace boost any & operator=(any rhs) { + any(rhs).swap(*this); + return *this; + } + +#else + any & operator=(const any& rhs) + { + any(rhs).swap(*this); + return *this; + } + + // move assignement + any & operator=(any&& rhs) BOOST_NOEXCEPT + { rhs.swap(*this); + any().swap(rhs); return *this; } + // Perfect forwarding of ValueType + template <class ValueType> + any & operator=(ValueType&& rhs) + { + any(static_cast<ValueType&&>(rhs)).swap(*this); + return *this; + } +#endif + public: // queries - bool empty() const + bool empty() const BOOST_NOEXCEPT { return !content; } - const std::type_info & type() const + void clear() BOOST_NOEXCEPT + { + any().swap(*this); + } + + const boost::typeindex::type_info& type() const BOOST_NOEXCEPT { - return content ? content->type() : typeid(void); + return content ? content->type() : boost::typeindex::type_id<void>().type_info(); } #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS @@ -106,7 +157,7 @@ namespace boost public: // queries - virtual const std::type_info & type() const = 0; + virtual const boost::typeindex::type_info& type() const BOOST_NOEXCEPT = 0; virtual placeholder * clone() const = 0; @@ -122,11 +173,17 @@ namespace boost { } +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + holder(ValueType&& value) + : held(static_cast< ValueType&& >(value)) + { + } +#endif public: // queries - virtual const std::type_info & type() const + virtual const boost::typeindex::type_info& type() const BOOST_NOEXCEPT { - return typeid(ValueType); + return boost::typeindex::type_id<ValueType>().type_info(); } virtual placeholder * clone() const @@ -147,10 +204,10 @@ namespace boost private: // representation template<typename ValueType> - friend ValueType * any_cast(any *); + friend ValueType * any_cast(any *) BOOST_NOEXCEPT; template<typename ValueType> - friend ValueType * unsafe_any_cast(any *); + friend ValueType * unsafe_any_cast(any *) BOOST_NOEXCEPT; #else @@ -161,11 +218,21 @@ namespace boost placeholder * content; }; + + inline void swap(any & lhs, any & rhs) BOOST_NOEXCEPT + { + lhs.swap(rhs); + } - class bad_any_cast : public std::bad_cast + class BOOST_SYMBOL_VISIBLE bad_any_cast : +#ifndef BOOST_NO_RTTI + public std::bad_cast +#else + public std::exception +#endif { public: - virtual const char * what() const throw() + virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW { return "boost::bad_any_cast: " "failed conversion using boost::any_cast"; @@ -173,20 +240,15 @@ namespace boost }; template<typename ValueType> - ValueType * any_cast(any * operand) + ValueType * any_cast(any * operand) BOOST_NOEXCEPT { - return operand && -#ifdef BOOST_AUX_ANY_TYPE_ID_NAME - std::strcmp(operand->type().name(), typeid(ValueType).name()) == 0 -#else - operand->type() == typeid(ValueType) -#endif - ? &static_cast<any::holder<ValueType> *>(operand->content)->held + return operand && operand->type() == boost::typeindex::type_id<ValueType>() + ? &static_cast<any::holder<BOOST_DEDUCED_TYPENAME remove_cv<ValueType>::type> *>(operand->content)->held : 0; } template<typename ValueType> - inline const ValueType * any_cast(const any * operand) + inline const ValueType * any_cast(const any * operand) BOOST_NOEXCEPT { return any_cast<ValueType>(const_cast<any *>(operand)); } @@ -196,35 +258,44 @@ namespace boost { typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref; -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - // If 'nonref' is still reference type, it means the user has not - // specialized 'remove_reference'. - - // Please use BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION macro - // to generate specialization of remove_reference for your class - // See type traits library documentation for details - BOOST_STATIC_ASSERT(!is_reference<nonref>::value); -#endif nonref * result = any_cast<nonref>(&operand); if(!result) boost::throw_exception(bad_any_cast()); - return *result; + + // Attempt to avoid construction of a temporary object in cases when + // `ValueType` is not a reference. Example: + // `static_cast<std::string>(*result);` + // which is equal to `std::string(*result);` + typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_< + boost::is_reference<ValueType>, + ValueType, + BOOST_DEDUCED_TYPENAME boost::add_reference<ValueType>::type + >::type ref_type; + + return static_cast<ref_type>(*result); } template<typename ValueType> inline ValueType any_cast(const any & operand) { typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref; + return any_cast<const nonref &>(const_cast<any &>(operand)); + } -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - // The comment in the above version of 'any_cast' explains when this - // assert is fired and what to do. - BOOST_STATIC_ASSERT(!is_reference<nonref>::value); +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template<typename ValueType> + inline ValueType any_cast(any&& operand) + { + BOOST_STATIC_ASSERT_MSG( + boost::is_rvalue_reference<ValueType&&>::value /*true if ValueType is rvalue or just a value*/ + || boost::is_const< typename boost::remove_reference<ValueType>::type >::value, + "boost::any_cast shall not be used for getting nonconst references to temporary objects" + ); + return any_cast<ValueType>(operand); + } #endif - return any_cast<const nonref &>(const_cast<any &>(operand)); - } // Note: The "unsafe" versions of any_cast are not part of the // public interface and may be removed at any time. They are @@ -232,13 +303,13 @@ namespace boost // use typeid() comparison, e.g., when our types may travel across // different shared libraries. template<typename ValueType> - inline ValueType * unsafe_any_cast(any * operand) + inline ValueType * unsafe_any_cast(any * operand) BOOST_NOEXCEPT { return &static_cast<any::holder<ValueType> *>(operand->content)->held; } template<typename ValueType> - inline const ValueType * unsafe_any_cast(const any * operand) + inline const ValueType * unsafe_any_cast(const any * operand) BOOST_NOEXCEPT { return unsafe_any_cast<ValueType>(const_cast<any *>(operand)); } |