Chris@16: //----------------------------------------------------------------------------- Chris@16: // boost variant/variant.hpp header file Chris@16: // See http://www.boost.org for updates, documentation, and revision history. Chris@16: //----------------------------------------------------------------------------- Chris@16: // Chris@16: // Copyright (c) 2002-2003 Eric Friedman, Itay Maman Chris@101: // Copyright (c) 2012-2014 Antony Polukhin Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. (See Chris@16: // accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: // Thanks to Adam Romanek for providing patches for exception-disabled env. Chris@16: Chris@16: #ifndef BOOST_VARIANT_VARIANT_HPP Chris@16: #define BOOST_VARIANT_VARIANT_HPP Chris@16: Chris@16: #include // for std::size_t Chris@16: #include // for placement new Chris@16: Chris@101: #include "boost/type_index.hpp" Chris@16: Chris@16: #include "boost/variant/detail/config.hpp" Chris@16: #include "boost/mpl/aux_/value_wknd.hpp" Chris@16: Chris@16: #include "boost/variant/variant_fwd.hpp" Chris@16: #include "boost/variant/detail/backup_holder.hpp" Chris@16: #include "boost/variant/detail/enable_recursive_fwd.hpp" Chris@16: #include "boost/variant/detail/forced_return.hpp" Chris@16: #include "boost/variant/detail/initializer.hpp" Chris@16: #include "boost/variant/detail/make_variant_list.hpp" Chris@16: #include "boost/variant/detail/over_sequence.hpp" Chris@16: #include "boost/variant/detail/visitation_impl.hpp" Chris@16: #include "boost/variant/detail/hash_variant.hpp" Chris@16: Chris@16: #include "boost/variant/detail/generic_result_type.hpp" Chris@16: #include "boost/variant/detail/move.hpp" Chris@16: Chris@16: #include "boost/detail/no_exceptions_support.hpp" Chris@16: #include "boost/detail/reference_content.hpp" Chris@16: #include "boost/aligned_storage.hpp" Chris@16: #include "boost/blank.hpp" Chris@16: #include "boost/math/common_factor_ct.hpp" Chris@16: #include "boost/static_assert.hpp" Chris@16: #include "boost/preprocessor/cat.hpp" Chris@16: #include "boost/preprocessor/repeat.hpp" Chris@16: #include "boost/type_traits/alignment_of.hpp" Chris@16: #include "boost/type_traits/add_const.hpp" Chris@16: #include "boost/type_traits/has_nothrow_constructor.hpp" Chris@16: #include "boost/type_traits/has_nothrow_copy.hpp" Chris@101: #include "boost/type_traits/is_nothrow_move_assignable.hpp" Chris@16: #include "boost/type_traits/is_nothrow_move_constructible.hpp" Chris@16: #include "boost/type_traits/is_const.hpp" Chris@16: #include "boost/type_traits/is_same.hpp" Chris@16: #include "boost/type_traits/is_rvalue_reference.hpp" Chris@16: #include "boost/utility/enable_if.hpp" Chris@16: #include "boost/utility/declval.hpp" Chris@16: #include "boost/variant/recursive_wrapper_fwd.hpp" Chris@16: #include "boost/variant/static_visitor.hpp" Chris@16: Chris@16: #include "boost/mpl/assert.hpp" Chris@16: #include "boost/mpl/begin_end.hpp" Chris@16: #include "boost/mpl/bool.hpp" Chris@16: #include "boost/mpl/deref.hpp" Chris@16: #include "boost/mpl/empty.hpp" Chris@16: #include "boost/mpl/eval_if.hpp" Chris@16: #include "boost/mpl/find_if.hpp" Chris@16: #include "boost/mpl/fold.hpp" Chris@16: #include "boost/mpl/front.hpp" Chris@16: #include "boost/mpl/identity.hpp" Chris@16: #include "boost/mpl/if.hpp" Chris@16: #include "boost/mpl/int.hpp" Chris@16: #include "boost/mpl/is_sequence.hpp" Chris@16: #include "boost/mpl/iterator_range.hpp" Chris@16: #include "boost/mpl/iter_fold_if.hpp" Chris@16: #include "boost/mpl/logical.hpp" Chris@16: #include "boost/mpl/max_element.hpp" Chris@16: #include "boost/mpl/next.hpp" Chris@16: #include "boost/mpl/not.hpp" Chris@16: #include "boost/mpl/pair.hpp" Chris@16: #include "boost/mpl/protect.hpp" Chris@16: #include "boost/mpl/push_front.hpp" Chris@16: #include "boost/mpl/same_as.hpp" Chris@16: #include "boost/mpl/size_t.hpp" Chris@16: #include "boost/mpl/sizeof.hpp" Chris@16: #include "boost/mpl/transform.hpp" Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // Implementation Macros: Chris@16: // Chris@16: // BOOST_VARIANT_VISITATION_UNROLLING_LIMIT Chris@16: // Defined in boost/variant/detail/visitation_impl.hpp. Chris@16: // Chris@16: // BOOST_VARIANT_MINIMIZE_SIZE Chris@16: // When #defined, implementation employs all known means to minimize the Chris@16: // size of variant obje cts. However, often unsuccessful due to alignment Chris@16: // issues, and potentially harmful to runtime speed, so not enabled by Chris@16: // default. (TODO: Investigate further.) Chris@16: Chris@16: #if defined(BOOST_VARIANT_MINIMIZE_SIZE) Chris@16: # include // for SCHAR_MAX Chris@16: # include "boost/mpl/eval_if.hpp" Chris@16: # include "boost/mpl/equal_to.hpp" Chris@16: # include "boost/mpl/identity.hpp" Chris@16: # include "boost/mpl/int.hpp" Chris@16: # include "boost/mpl/if.hpp" Chris@16: # include "boost/mpl/less.hpp" Chris@16: # include "boost/mpl/long.hpp" Chris@16: # include "boost/mpl/O1_size.hpp" Chris@16: #endif Chris@16: Chris@16: Chris@16: namespace boost { Chris@16: Chris@16: namespace detail { namespace variant { Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // (detail) metafunction max_value Chris@16: // Chris@16: // Finds the maximum value of the unary metafunction F over Sequence. Chris@16: // Chris@16: template Chris@16: struct max_value Chris@16: { Chris@16: private: // helpers, for metafunction result (below) Chris@16: Chris@16: typedef typename mpl::transform1::type transformed_; Chris@16: typedef typename mpl::max_element::type max_it; Chris@16: Chris@16: public: // metafunction result Chris@16: Chris@16: typedef typename mpl::deref::type Chris@16: type; Chris@16: Chris@16: }; Chris@16: Chris@16: struct add_alignment Chris@16: { Chris@16: template Chris@16: struct apply Chris@16: : mpl::size_t< Chris@16: ::boost::math::static_lcm< Chris@16: BOOST_MPL_AUX_VALUE_WKND(State)::value Chris@16: , ::boost::alignment_of::value Chris@16: >::value Chris@16: > Chris@16: {}; Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // (detail) metafunction find_fallback_type Chris@16: // Chris@16: // Provides a fallback (i.e., nothrow default-constructible) type from the Chris@16: // specified sequence, or no_fallback_type if not found. Chris@16: // Chris@16: // This implementation is designed to prefer boost::blank over other potential Chris@16: // fallback types, regardless of its position in the specified sequence. Chris@16: // Chris@16: Chris@16: class no_fallback_type; Chris@16: Chris@16: struct find_fallback_type_pred Chris@16: { Chris@16: template Chris@16: struct apply Chris@16: { Chris@16: private: Chris@16: typedef typename mpl::deref::type t_; Chris@16: Chris@16: public: Chris@16: typedef mpl::not_< has_nothrow_constructor > type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct find_fallback_type Chris@16: { Chris@16: private: // helpers, for metafunction result (below) Chris@16: Chris@16: typedef typename mpl::end::type end_it; Chris@16: Chris@16: // [Find the first suitable fallback type...] Chris@16: Chris@16: typedef typename mpl::iter_fold_if< Chris@16: Types Chris@16: , mpl::int_<0>, mpl::protect< mpl::next<> > Chris@16: , mpl::protect< find_fallback_type_pred > Chris@16: >::type first_result_; Chris@16: Chris@16: typedef typename first_result_::first first_result_index; Chris@16: typedef typename first_result_::second first_result_it; Chris@16: Chris@16: // [...now search the rest of the sequence for boost::blank...] Chris@16: Chris@16: typedef typename mpl::iter_fold_if< Chris@16: mpl::iterator_range< first_result_it,end_it > Chris@16: , first_result_index, mpl::protect< mpl::next<> > Chris@16: , mpl::protect< mpl::not_same_as > Chris@16: >::type second_result_; Chris@16: Chris@16: typedef typename second_result_::second second_result_it; Chris@16: Chris@16: public: // metafunction result Chris@16: Chris@16: // [...and return the results of the search:] Chris@16: typedef typename mpl::eval_if< Chris@16: is_same< second_result_it,end_it > Chris@16: , mpl::if_< Chris@16: is_same< first_result_it,end_it > Chris@16: , mpl::pair< no_fallback_type,no_fallback_type > Chris@16: , first_result_ Chris@16: > Chris@16: , mpl::identity< second_result_ > Chris@16: >::type type; Chris@16: Chris@16: }; Chris@16: Chris@16: #ifndef BOOST_NO_CXX11_NOEXCEPT Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@101: // (detail) metafunction is_variant_move_noexcept_constructible Chris@16: // Chris@16: // Returns true_type if all the types are nothrow move constructible. Chris@16: // Chris@16: template Chris@101: struct is_variant_move_noexcept_constructible { Chris@16: typedef typename boost::mpl::find_if< Chris@16: Types, mpl::not_ > Chris@16: >::type iterator_t; Chris@16: Chris@16: typedef typename boost::mpl::end::type end_t; Chris@16: typedef typename boost::is_same< Chris@16: iterator_t, end_t Chris@16: >::type type; Chris@16: }; Chris@101: Chris@101: /////////////////////////////////////////////////////////////////////////////// Chris@101: // (detail) metafunction is_variant_move_noexcept_assignable Chris@101: // Chris@101: // Returns true_type if all the types are nothrow move constructible. Chris@101: // Chris@101: template Chris@101: struct is_variant_move_noexcept_assignable { Chris@101: typedef typename boost::mpl::find_if< Chris@101: Types, mpl::not_ > Chris@101: >::type iterator_t; Chris@101: Chris@101: typedef typename boost::mpl::end::type end_t; Chris@101: typedef typename boost::is_same< Chris@101: iterator_t, end_t Chris@101: >::type type; Chris@101: }; Chris@16: #endif // BOOST_NO_CXX11_NOEXCEPT Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // (detail) metafunction make_storage Chris@16: // Chris@16: // Provides an aligned storage type capable of holding any of the types Chris@16: // specified in the given type-sequence. Chris@16: // Chris@16: Chris@16: template Chris@16: struct make_storage Chris@16: { Chris@16: private: // helpers, for metafunction result (below) Chris@16: Chris@16: typedef typename mpl::eval_if< Chris@16: NeverUsesBackupFlag Chris@16: , mpl::identity< Types > Chris@16: , mpl::push_front< Chris@16: Types, backup_holder Chris@16: > Chris@16: >::type types; Chris@16: Chris@16: typedef typename max_value< Chris@16: types, mpl::sizeof_ Chris@16: >::type max_size; Chris@16: Chris@16: #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551)) Chris@16: Chris@16: typedef typename mpl::fold< Chris@16: types Chris@16: , mpl::size_t<1> Chris@16: , add_alignment Chris@16: >::type max_alignment; Chris@16: Chris@16: #else // borland Chris@16: Chris@16: // temporary workaround -- use maximal alignment Chris@16: typedef mpl::size_t< -1 > max_alignment; Chris@16: Chris@16: #endif // borland workaround Chris@16: Chris@16: public: // metafunction result Chris@16: Chris@16: typedef ::boost::aligned_storage< Chris@16: BOOST_MPL_AUX_VALUE_WKND(max_size)::value Chris@16: , BOOST_MPL_AUX_VALUE_WKND(max_alignment)::value Chris@16: > type; Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // (detail) class destroyer Chris@16: // Chris@16: // Internal visitor that destroys the value it visits. Chris@16: // Chris@16: struct destroyer Chris@16: : public static_visitor<> Chris@16: { Chris@16: public: // visitor interfaces Chris@16: Chris@16: template Chris@16: BOOST_VARIANT_AUX_RETURN_VOID_TYPE Chris@101: internal_visit(T& operand, int) const BOOST_NOEXCEPT Chris@16: { Chris@101: operand.~T(); // must be noexcept Chris@16: Chris@16: #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551)) || \ Chris@16: BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) Chris@16: operand; // suppresses warnings Chris@16: #endif Chris@16: Chris@16: BOOST_VARIANT_AUX_RETURN_VOID; Chris@16: } Chris@16: Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // (detail) class template known_get Chris@16: // Chris@16: // Visitor that returns a reference to content of the specified type. Chris@16: // Chris@16: // Precondition: visited variant MUST contain logical content of type T. Chris@16: // Chris@16: template Chris@16: class known_get Chris@16: : public static_visitor Chris@16: { Chris@16: Chris@16: public: // visitor interface Chris@16: Chris@16: T& operator()(T& operand) const BOOST_NOEXCEPT Chris@16: { Chris@16: return operand; Chris@16: } Chris@16: Chris@16: template Chris@16: T& operator()(U&) const Chris@16: { Chris@16: // logical error to be here: see precondition above Chris@16: return ::boost::detail::variant::forced_return< T& >(); Chris@16: } Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // (detail) class copy_into Chris@16: // Chris@16: // Internal visitor that copies the value it visits into the given buffer. Chris@16: // Chris@16: class copy_into Chris@16: : public static_visitor<> Chris@16: { Chris@16: private: // representation Chris@16: Chris@16: void* storage_; Chris@16: Chris@16: public: // structors Chris@16: Chris@16: explicit copy_into(void* storage) BOOST_NOEXCEPT Chris@16: : storage_(storage) Chris@16: { Chris@16: } Chris@16: Chris@16: public: // internal visitor interface Chris@16: Chris@16: template Chris@16: BOOST_VARIANT_AUX_RETURN_VOID_TYPE Chris@16: internal_visit(boost::detail::variant::backup_holder& operand, long) const Chris@16: { Chris@16: new(storage_) T( operand.get() ); Chris@16: BOOST_VARIANT_AUX_RETURN_VOID; Chris@16: } Chris@16: Chris@16: template Chris@16: BOOST_VARIANT_AUX_RETURN_VOID_TYPE Chris@16: internal_visit(const boost::detail::variant::backup_holder& operand, long) const Chris@16: { Chris@16: new(storage_) T( operand.get() ); Chris@16: BOOST_VARIANT_AUX_RETURN_VOID; Chris@16: } Chris@16: Chris@16: template Chris@16: BOOST_VARIANT_AUX_RETURN_VOID_TYPE Chris@16: internal_visit(const T& operand, int) const Chris@16: { Chris@16: new(storage_) T(operand); Chris@16: BOOST_VARIANT_AUX_RETURN_VOID; Chris@16: } Chris@16: Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // (detail) class move_into Chris@16: // Chris@16: // Internal visitor that moves the value it visits into the given buffer. Chris@16: // Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: class move_into Chris@16: : public static_visitor<> Chris@16: { Chris@16: private: // representation Chris@16: Chris@16: void* storage_; Chris@16: Chris@16: public: // structors Chris@16: Chris@16: explicit move_into(void* storage) BOOST_NOEXCEPT Chris@16: : storage_(storage) Chris@16: { Chris@16: } Chris@16: Chris@16: public: // internal visitor interface Chris@16: Chris@16: template Chris@16: BOOST_VARIANT_AUX_RETURN_VOID_TYPE Chris@16: internal_visit(boost::detail::variant::backup_holder& operand, long) const Chris@16: { Chris@16: new(storage_) T( ::boost::detail::variant::move(operand.get()) ); Chris@16: BOOST_VARIANT_AUX_RETURN_VOID; Chris@16: } Chris@16: Chris@16: template Chris@16: BOOST_VARIANT_AUX_RETURN_VOID_TYPE Chris@16: internal_visit(T& operand, int) const BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T(boost::declval()))) Chris@16: { Chris@16: new(storage_) T(::boost::detail::variant::move(operand)); Chris@16: BOOST_VARIANT_AUX_RETURN_VOID; Chris@16: } Chris@16: }; Chris@16: #endif Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // (detail) class assign_storage Chris@16: // Chris@16: // Internal visitor that assigns the given storage (which must be a Chris@16: // constructed value of the same type) to the value it visits. Chris@16: // Chris@16: struct assign_storage Chris@16: : public static_visitor<> Chris@16: { Chris@16: private: // representation Chris@16: Chris@16: const void* rhs_storage_; Chris@16: Chris@16: public: // structors Chris@16: Chris@16: explicit assign_storage(const void* rhs_storage) BOOST_NOEXCEPT Chris@16: : rhs_storage_(rhs_storage) Chris@16: { Chris@16: } Chris@16: Chris@16: public: // internal visitor interfaces Chris@16: Chris@16: template Chris@16: BOOST_VARIANT_AUX_RETURN_VOID_TYPE Chris@16: internal_visit(backup_holder& lhs_content, long) const Chris@16: { Chris@16: lhs_content.get() Chris@16: = static_cast< const backup_holder* >(rhs_storage_)->get(); Chris@16: BOOST_VARIANT_AUX_RETURN_VOID; Chris@16: } Chris@16: Chris@16: template Chris@16: BOOST_VARIANT_AUX_RETURN_VOID_TYPE Chris@16: internal_visit(const backup_holder& lhs_content, long) const Chris@16: { Chris@16: lhs_content.get() Chris@16: = static_cast< const backup_holder* >(rhs_storage_)->get(); Chris@16: BOOST_VARIANT_AUX_RETURN_VOID; Chris@16: } Chris@16: Chris@16: template Chris@16: BOOST_VARIANT_AUX_RETURN_VOID_TYPE Chris@16: internal_visit(T& lhs_content, int) const Chris@16: { Chris@16: // NOTE TO USER : Chris@16: // Compile error here indicates one of variant's bounded types does Chris@16: // not meet the requirements of the Assignable concept. Thus, Chris@16: // variant is not Assignable. Chris@16: // Chris@16: // Hint: Are any of the bounded types const-qualified or references? Chris@16: // Chris@16: lhs_content = *static_cast< const T* >(rhs_storage_); Chris@16: BOOST_VARIANT_AUX_RETURN_VOID; Chris@16: } Chris@16: Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // (detail) class move_storage Chris@16: // Chris@16: // Internal visitor that moves the given storage (which must be a Chris@16: // constructed value of the same type) to the value it visits. Chris@16: // Chris@16: struct move_storage Chris@16: : public static_visitor<> Chris@16: { Chris@16: private: // representation Chris@16: Chris@16: void* rhs_storage_; Chris@16: Chris@16: public: // structors Chris@16: Chris@16: explicit move_storage(void* rhs_storage) BOOST_NOEXCEPT Chris@16: : rhs_storage_(rhs_storage) Chris@16: { Chris@16: } Chris@16: Chris@16: public: // internal visitor interfaces Chris@16: Chris@16: template Chris@16: BOOST_VARIANT_AUX_RETURN_VOID_TYPE Chris@16: internal_visit(backup_holder& lhs_content, long) const Chris@16: { Chris@16: lhs_content.get() Chris@16: = ::boost::detail::variant::move(static_cast* >(rhs_storage_)->get()); Chris@16: BOOST_VARIANT_AUX_RETURN_VOID; Chris@16: } Chris@16: Chris@16: template Chris@16: BOOST_VARIANT_AUX_RETURN_VOID_TYPE Chris@16: internal_visit(const backup_holder& lhs_content, long) const Chris@16: { Chris@16: lhs_content.get() Chris@16: = ::boost::detail::variant::move(static_cast* >(rhs_storage_)->get()); Chris@16: BOOST_VARIANT_AUX_RETURN_VOID; Chris@16: } Chris@16: Chris@16: template Chris@16: BOOST_VARIANT_AUX_RETURN_VOID_TYPE Chris@16: internal_visit(T& lhs_content, int) const Chris@16: { Chris@16: // NOTE TO USER : Chris@16: // Compile error here indicates one of variant's bounded types does Chris@16: // not meet the requirements of the Assignable concept. Thus, Chris@16: // variant is not Assignable. Chris@16: // Chris@16: // Hint: Are any of the bounded types const-qualified or references? Chris@16: // Chris@16: lhs_content = ::boost::detail::variant::move(*static_cast(rhs_storage_)); Chris@16: BOOST_VARIANT_AUX_RETURN_VOID; Chris@16: } Chris@16: Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // (detail) class direct_assigner Chris@16: // Chris@16: // Generic static visitor that: if and only if the visited value is of the Chris@16: // specified type, assigns the given value to the visited value and returns Chris@16: // true; else returns false. Chris@16: // Chris@16: template Chris@16: class direct_assigner Chris@16: : public static_visitor Chris@16: { Chris@16: private: // representation Chris@16: Chris@16: const T& rhs_; Chris@16: Chris@16: public: // structors Chris@16: Chris@16: explicit direct_assigner(const T& rhs) BOOST_NOEXCEPT Chris@16: : rhs_(rhs) Chris@16: { Chris@16: } Chris@16: Chris@16: public: // visitor interface Chris@16: Chris@16: bool operator()(T& lhs) Chris@16: { Chris@16: lhs = rhs_; Chris@16: return true; Chris@16: } Chris@16: Chris@16: template Chris@16: bool operator()(U&) BOOST_NOEXCEPT Chris@16: { Chris@16: return false; Chris@16: } Chris@16: Chris@16: #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) Chris@16: private: Chris@16: // silence MSVC warning C4512: assignment operator could not be generated Chris@16: direct_assigner& operator= (direct_assigner const&); Chris@16: #endif Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // (detail) class direct_mover Chris@16: // Chris@16: // Generic static visitor that: if and only if the visited value is of the Chris@16: // specified type, move assigns the given value to the visited value and returns Chris@16: // true; else returns false. Chris@16: // Chris@16: template Chris@16: class direct_mover Chris@16: : public static_visitor Chris@16: { Chris@16: private: // representation Chris@16: Chris@16: T& rhs_; Chris@16: Chris@16: public: // structors Chris@16: Chris@16: explicit direct_mover(T& rhs) BOOST_NOEXCEPT Chris@16: : rhs_(rhs) Chris@16: { Chris@16: } Chris@16: Chris@16: public: // visitor interface Chris@16: Chris@16: bool operator()(T& lhs) Chris@16: { Chris@16: lhs = ::boost::detail::variant::move(rhs_); Chris@16: return true; Chris@16: } Chris@16: Chris@16: template Chris@16: bool operator()(U&) BOOST_NOEXCEPT Chris@16: { Chris@16: return false; Chris@16: } Chris@16: Chris@16: #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) Chris@16: private: Chris@16: // silence MSVC warning C4512: assignment operator could not be generated Chris@16: direct_mover& operator= (direct_mover const&); Chris@16: #endif Chris@16: }; Chris@16: Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // (detail) class backup_assigner Chris@16: // Chris@16: // Internal visitor that "assigns" the given value to the visited value, Chris@16: // using backup to recover if the destroy-copy sequence fails. Chris@16: // Chris@16: // NOTE: This needs to be a friend of variant, as it needs access to Chris@16: // indicate_which, indicate_backup_which, etc. Chris@16: // Chris@16: template Chris@16: class backup_assigner Chris@16: : public static_visitor<> Chris@16: { Chris@16: private: // representation Chris@16: Chris@16: Variant& lhs_; Chris@16: int rhs_which_; Chris@16: const void* rhs_content_; Chris@16: void (*copy_rhs_content_)(void*, const void*); Chris@16: Chris@16: public: // structors Chris@16: Chris@16: template Chris@16: backup_assigner(Variant& lhs, int rhs_which, const RhsT& rhs_content) Chris@16: : lhs_(lhs) Chris@16: , rhs_which_(rhs_which) Chris@16: , rhs_content_(&rhs_content) Chris@16: , copy_rhs_content_(&construct_impl) Chris@16: { Chris@16: } Chris@16: Chris@16: private: // helpers, for visitor interface (below) Chris@16: Chris@16: template Chris@16: static void construct_impl(void* addr, const void* obj) Chris@16: { Chris@16: new(addr) RhsT(*static_cast(obj)); Chris@16: } Chris@16: Chris@16: template Chris@16: void backup_assign_impl( Chris@101: backup_holder& lhs_content Chris@101: , mpl::false_ // is_nothrow_move_constructible Chris@101: , long Chris@101: ) Chris@101: { Chris@101: // Move lhs content to backup... Chris@101: backup_holder backup_lhs_content(0); Chris@101: backup_lhs_content.swap(lhs_content); // nothrow Chris@101: Chris@101: // ...destroy lhs content... Chris@101: lhs_content.~backup_holder(); // nothrow Chris@101: Chris@101: BOOST_TRY Chris@101: { Chris@101: // ...and attempt to copy rhs content into lhs storage: Chris@101: copy_rhs_content_(lhs_.storage_.address(), rhs_content_); Chris@101: } Chris@101: BOOST_CATCH (...) Chris@101: { Chris@101: // In case of failure, copy backup pointer to lhs storage... Chris@101: new(lhs_.storage_.address()) Chris@101: backup_holder( 0 ); // nothrow Chris@101: Chris@101: static_cast* >(lhs_.storage_.address()) Chris@101: ->swap(backup_lhs_content); // nothrow Chris@101: Chris@101: // ...and rethrow: Chris@101: BOOST_RETHROW; Chris@101: } Chris@101: BOOST_CATCH_END Chris@101: Chris@101: // In case of success, indicate new content type: Chris@101: lhs_.indicate_which(rhs_which_); // nothrow Chris@101: } Chris@101: Chris@101: template Chris@101: void backup_assign_impl( Chris@16: LhsT& lhs_content Chris@16: , mpl::true_ // is_nothrow_move_constructible Chris@101: , int Chris@16: ) Chris@16: { Chris@16: // Move lhs content to backup... Chris@16: LhsT backup_lhs_content( Chris@16: ::boost::detail::variant::move(lhs_content) Chris@16: ); // nothrow Chris@16: Chris@16: // ...destroy lhs content... Chris@16: lhs_content.~LhsT(); // nothrow Chris@16: Chris@16: BOOST_TRY Chris@16: { Chris@16: // ...and attempt to copy rhs content into lhs storage: Chris@16: copy_rhs_content_(lhs_.storage_.address(), rhs_content_); Chris@16: } Chris@16: BOOST_CATCH (...) Chris@16: { Chris@16: // In case of failure, restore backup content to lhs storage... Chris@16: new(lhs_.storage_.address()) Chris@16: LhsT( Chris@16: ::boost::detail::variant::move(backup_lhs_content) Chris@16: ); // nothrow Chris@16: Chris@16: // ...and rethrow: Chris@16: BOOST_RETHROW; Chris@16: } Chris@16: BOOST_CATCH_END Chris@16: Chris@16: // In case of success, indicate new content type: Chris@16: lhs_.indicate_which(rhs_which_); // nothrow Chris@16: } Chris@16: Chris@16: template Chris@16: void backup_assign_impl( Chris@16: LhsT& lhs_content Chris@16: , mpl::false_ // is_nothrow_move_constructible Chris@101: , int Chris@16: ) Chris@16: { Chris@16: // Backup lhs content... Chris@16: LhsT* backup_lhs_ptr = new LhsT(lhs_content); Chris@16: Chris@16: // ...destroy lhs content... Chris@16: lhs_content.~LhsT(); // nothrow Chris@16: Chris@16: BOOST_TRY Chris@16: { Chris@16: // ...and attempt to copy rhs content into lhs storage: Chris@16: copy_rhs_content_(lhs_.storage_.address(), rhs_content_); Chris@16: } Chris@16: BOOST_CATCH (...) Chris@16: { Chris@16: // In case of failure, copy backup pointer to lhs storage... Chris@16: new(lhs_.storage_.address()) Chris@16: backup_holder( backup_lhs_ptr ); // nothrow Chris@16: Chris@16: // ...indicate now using backup... Chris@16: lhs_.indicate_backup_which( lhs_.which() ); // nothrow Chris@16: Chris@16: // ...and rethrow: Chris@16: BOOST_RETHROW; Chris@16: } Chris@16: BOOST_CATCH_END Chris@16: Chris@16: // In case of success, indicate new content type... Chris@16: lhs_.indicate_which(rhs_which_); // nothrow Chris@16: Chris@16: // ...and delete backup: Chris@16: delete backup_lhs_ptr; // nothrow Chris@16: } Chris@16: Chris@16: public: // visitor interface Chris@16: Chris@16: template Chris@16: BOOST_VARIANT_AUX_RETURN_VOID_TYPE Chris@16: internal_visit(LhsT& lhs_content, int) Chris@16: { Chris@16: typedef typename is_nothrow_move_constructible::type Chris@16: nothrow_move; Chris@16: Chris@101: backup_assign_impl( lhs_content, nothrow_move(), 1L); Chris@16: Chris@16: BOOST_VARIANT_AUX_RETURN_VOID; Chris@16: } Chris@16: Chris@16: #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) Chris@16: private: Chris@16: // silence MSVC warning C4512: assignment operator could not be generated Chris@16: backup_assigner& operator= (backup_assigner const&); Chris@16: #endif Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // (detail) class swap_with Chris@16: // Chris@16: // Visitor that swaps visited value with content of given variant. Chris@16: // Chris@16: // Precondition: Given variant MUST have same logical type as visited value. Chris@16: // Chris@16: template Chris@16: struct swap_with Chris@16: : public static_visitor<> Chris@16: { Chris@16: private: // representation Chris@16: Chris@16: Variant& toswap_; Chris@16: Chris@16: public: // structors Chris@16: Chris@101: explicit swap_with(Variant& toswap) BOOST_NOEXCEPT Chris@16: : toswap_(toswap) Chris@16: { Chris@16: } Chris@16: Chris@16: public: // internal visitor interfaces Chris@16: Chris@16: template Chris@16: void operator()(T& operand) const Chris@16: { Chris@16: // Since the precondition ensures types are same, get T... Chris@16: known_get getter; Chris@16: T& other = toswap_.apply_visitor(getter); Chris@16: Chris@16: // ...and swap: Chris@16: ::boost::detail::variant::move_swap( operand, other ); Chris@16: } Chris@16: Chris@16: private: Chris@16: swap_with& operator=(const swap_with&); Chris@16: Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // (detail) class reflect Chris@16: // Chris@16: // Generic static visitor that performs a typeid on the value it visits. Chris@16: // Chris@16: Chris@16: class reflect Chris@101: : public static_visitor Chris@16: { Chris@16: public: // visitor interfaces Chris@16: Chris@16: template Chris@101: const boost::typeindex::type_info& operator()(const T&) const BOOST_NOEXCEPT Chris@16: { Chris@101: return boost::typeindex::type_id().type_info(); Chris@16: } Chris@16: Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // (detail) class comparer Chris@16: // Chris@16: // Generic static visitor that compares the content of the given lhs variant Chris@16: // with the visited rhs content using Comp. Chris@16: // Chris@16: // Precondition: lhs.which() == rhs.which() Chris@16: // Chris@16: template Chris@16: class comparer Chris@16: : public static_visitor Chris@16: { Chris@16: private: // representation Chris@16: Chris@16: const Variant& lhs_; Chris@16: Chris@16: public: // structors Chris@16: Chris@16: explicit comparer(const Variant& lhs) BOOST_NOEXCEPT Chris@16: : lhs_(lhs) Chris@16: { Chris@16: } Chris@16: Chris@16: public: // visitor interfaces Chris@16: Chris@16: template Chris@16: bool operator()(const T& rhs_content) const Chris@16: { Chris@16: // Since the precondition ensures lhs and rhs types are same, get T... Chris@16: known_get getter; Chris@16: const T& lhs_content = lhs_.apply_visitor(getter); Chris@16: Chris@16: // ...and compare lhs and rhs contents: Chris@16: return Comp()(lhs_content, rhs_content); Chris@16: } Chris@16: Chris@16: private: Chris@16: comparer& operator=(const comparer&); Chris@16: Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // (detail) class equal_comp Chris@16: // Chris@16: // Generic function object compares lhs with rhs using operator==. Chris@16: // Chris@16: struct equal_comp Chris@16: { Chris@16: template Chris@16: bool operator()(const T& lhs, const T& rhs) const Chris@16: { Chris@16: return lhs == rhs; Chris@16: } Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // (detail) class less_comp Chris@16: // Chris@16: // Generic function object compares lhs with rhs using operator<. Chris@16: // Chris@16: struct less_comp Chris@16: { Chris@16: template Chris@16: bool operator()(const T& lhs, const T& rhs) const Chris@16: { Chris@16: return lhs < rhs; Chris@16: } Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // (detail) class template invoke_visitor Chris@16: // Chris@16: // Internal visitor that invokes the given visitor using: Chris@16: // * for wrappers (e.g., recursive_wrapper), the wrapper's held value. Chris@16: // * for all other values, the value itself. Chris@16: // Chris@16: template Chris@16: class invoke_visitor Chris@16: { Chris@16: private: // representation Chris@16: Chris@16: Visitor& visitor_; Chris@16: Chris@16: public: // visitor typedefs Chris@16: Chris@16: typedef typename Visitor::result_type Chris@16: result_type; Chris@16: Chris@16: public: // structors Chris@16: Chris@16: explicit invoke_visitor(Visitor& visitor) BOOST_NOEXCEPT Chris@16: : visitor_(visitor) Chris@16: { Chris@16: } Chris@16: Chris@16: #if !defined(BOOST_NO_VOID_RETURNS) Chris@16: Chris@16: public: // internal visitor interfaces Chris@16: Chris@16: template Chris@16: result_type internal_visit(T& operand, int) Chris@16: { Chris@16: return visitor_(operand); Chris@16: } Chris@16: Chris@16: # if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564)) Chris@16: template Chris@16: result_type internal_visit(const T& operand, int) Chris@16: { Chris@16: return visitor_(operand); Chris@16: } Chris@16: # endif Chris@16: Chris@16: #else // defined(BOOST_NO_VOID_RETURNS) Chris@16: Chris@16: private: // helpers, for internal visitor interfaces (below) Chris@16: Chris@16: template Chris@16: BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type) Chris@16: visit_impl(T& operand, mpl::false_) Chris@16: { Chris@16: return visitor_(operand); Chris@16: } Chris@16: Chris@16: template Chris@16: BOOST_VARIANT_AUX_RETURN_VOID_TYPE Chris@16: visit_impl(T& operand, mpl::true_) Chris@16: { Chris@16: visitor_(operand); Chris@16: BOOST_VARIANT_AUX_RETURN_VOID; Chris@16: } Chris@16: Chris@16: public: // internal visitor interfaces Chris@16: Chris@16: template Chris@16: BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type) Chris@16: internal_visit(T& operand, int) Chris@16: { Chris@16: typedef typename is_same::type Chris@16: has_void_result_type; Chris@16: Chris@16: return visit_impl(operand, has_void_result_type()); Chris@16: } Chris@16: Chris@16: #endif // BOOST_NO_VOID_RETURNS) workaround Chris@16: Chris@16: public: // internal visitor interfaces, cont. Chris@16: Chris@16: template Chris@16: BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type) Chris@16: internal_visit(boost::recursive_wrapper& operand, long) Chris@16: { Chris@16: return internal_visit( operand.get(), 1L ); Chris@16: } Chris@16: Chris@16: template Chris@16: BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type) Chris@16: internal_visit(const boost::recursive_wrapper& operand, long) Chris@16: { Chris@16: return internal_visit( operand.get(), 1L ); Chris@16: } Chris@16: Chris@16: template Chris@16: BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type) Chris@16: internal_visit(boost::detail::reference_content& operand, long) Chris@16: { Chris@16: return internal_visit( operand.get(), 1L ); Chris@16: } Chris@16: Chris@16: template Chris@16: BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type) Chris@16: internal_visit(const boost::detail::reference_content& operand, long) Chris@16: { Chris@16: return internal_visit( operand.get(), 1L ); Chris@16: } Chris@16: Chris@16: template Chris@16: BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type) Chris@16: internal_visit(boost::detail::variant::backup_holder& operand, long) Chris@16: { Chris@16: return internal_visit( operand.get(), 1L ); Chris@16: } Chris@16: Chris@16: template Chris@16: BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type) Chris@16: internal_visit(const boost::detail::variant::backup_holder& operand, long) Chris@16: { Chris@16: return internal_visit( operand.get(), 1L ); Chris@16: } Chris@16: Chris@16: #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) Chris@16: private: Chris@16: // silence MSVC warning C4512: assignment operator could not be generated Chris@16: invoke_visitor& operator= (invoke_visitor const&); Chris@16: #endif Chris@16: }; Chris@16: Chris@16: }} // namespace detail::variant Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // class template variant (concept inspired by Andrei Alexandrescu) Chris@16: // Chris@16: // See docs and boost/variant/variant_fwd.hpp for more information. Chris@16: // Chris@16: template < Chris@16: typename T0_ Chris@16: , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename T) Chris@16: > Chris@16: class variant Chris@16: { Chris@16: private: // helpers, for typedefs (below) Chris@16: Chris@16: typedef variant wknd_self_t; Chris@16: Chris@16: struct is_recursive_ Chris@16: : detail::variant::is_recursive_flag Chris@16: { Chris@16: }; Chris@16: Chris@16: typedef typename mpl::eval_if< Chris@16: is_recursive_ Chris@16: , T0_ Chris@16: , mpl::identity< T0_ > Chris@16: >::type unwrapped_T0_; Chris@16: Chris@16: struct is_sequence_based_ Chris@16: : detail::variant::is_over_sequence Chris@16: { Chris@16: }; Chris@16: Chris@16: #if !defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT) Chris@16: Chris@16: private: // helpers, for typedefs (below) Chris@16: Chris@16: typedef typename mpl::eval_if< Chris@16: is_sequence_based_ Chris@16: , unwrapped_T0_ // over_sequence<...>::type Chris@16: , detail::variant::make_variant_list< Chris@16: unwrapped_T0_ Chris@16: , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T) Chris@16: > Chris@16: >::type specified_types; Chris@16: Chris@16: BOOST_STATIC_ASSERT(( Chris@16: ::boost::mpl::not_< mpl::empty >::value Chris@16: )); Chris@16: Chris@16: typedef typename mpl::eval_if< Chris@16: is_recursive_ Chris@16: , mpl::transform< Chris@16: specified_types Chris@16: , mpl::protect< Chris@16: detail::variant::quoted_enable_recursive Chris@16: > Chris@16: > Chris@16: , mpl::identity< specified_types > Chris@16: >::type recursive_enabled_types; Chris@16: Chris@16: public: // public typedefs Chris@16: Chris@16: typedef typename mpl::transform< Chris@16: recursive_enabled_types Chris@16: , unwrap_recursive Chris@16: >::type types; Chris@16: Chris@16: private: // internal typedefs Chris@16: Chris@16: typedef typename mpl::transform< Chris@16: recursive_enabled_types Chris@16: , mpl::protect< detail::make_reference_content<> > Chris@16: >::type internal_types; Chris@16: Chris@16: typedef typename mpl::front< Chris@16: internal_types Chris@16: >::type internal_T0; Chris@16: Chris@16: #else // defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT) Chris@16: Chris@16: private: // helpers, for typedefs (below) Chris@16: Chris@16: typedef unwrapped_T0_ T0; Chris@16: Chris@16: #define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS(z,N,_) \ Chris@16: typedef typename mpl::eval_if< \ Chris@16: is_recursive_ \ Chris@16: , detail::variant::enable_recursive< \ Chris@16: BOOST_PP_CAT(T,N) \ Chris@16: , wknd_self_t \ Chris@16: > \ Chris@16: , mpl::identity< BOOST_PP_CAT(T,N) > \ Chris@16: >::type BOOST_PP_CAT(recursive_enabled_T,N); \ Chris@16: /**/ Chris@16: Chris@16: BOOST_PP_REPEAT( Chris@16: BOOST_VARIANT_LIMIT_TYPES Chris@16: , BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS Chris@16: , _ Chris@16: ) Chris@16: Chris@16: #undef BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS Chris@16: Chris@16: #define BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS(z,N,_) \ Chris@16: typedef typename unwrap_recursive< \ Chris@16: BOOST_PP_CAT(recursive_enabled_T,N) \ Chris@16: >::type BOOST_PP_CAT(public_T,N); \ Chris@16: /**/ Chris@16: Chris@16: BOOST_PP_REPEAT( Chris@16: BOOST_VARIANT_LIMIT_TYPES Chris@16: , BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS Chris@16: , _ Chris@16: ) Chris@16: Chris@16: #undef BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS Chris@16: Chris@16: public: // public typedefs Chris@16: Chris@16: typedef typename detail::variant::make_variant_list< Chris@16: BOOST_VARIANT_ENUM_PARAMS(public_T) Chris@16: >::type types; Chris@16: Chris@16: private: // helpers, for internal typedefs (below) Chris@16: Chris@16: #define BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS(z,N,_) \ Chris@16: typedef detail::make_reference_content< \ Chris@16: BOOST_PP_CAT(recursive_enabled_T,N) \ Chris@16: >::type BOOST_PP_CAT(internal_T,N); \ Chris@16: /**/ Chris@16: Chris@16: BOOST_PP_REPEAT( Chris@16: BOOST_VARIANT_LIMIT_TYPES Chris@16: , BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS Chris@16: , _ Chris@16: ) Chris@16: Chris@16: #undef BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS Chris@16: Chris@16: private: // internal typedefs Chris@16: Chris@16: typedef typename detail::variant::make_variant_list< Chris@16: BOOST_VARIANT_ENUM_PARAMS(internal_T) Chris@16: >::type internal_types; Chris@16: Chris@16: private: // static precondition assertions Chris@16: Chris@16: // NOTE TO USER : Chris@16: // variant< type-sequence > syntax is not supported on this compiler! Chris@16: // Chris@16: BOOST_MPL_ASSERT_NOT(( is_sequence_based_ )); Chris@16: Chris@16: #endif // BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT workaround Chris@16: Chris@16: private: // helpers, for representation (below) Chris@16: Chris@16: typedef typename detail::variant::find_fallback_type< Chris@16: internal_types Chris@16: >::type fallback_type_result_; Chris@16: Chris@16: typedef typename fallback_type_result_::first Chris@16: fallback_type_index_; Chris@16: typedef typename fallback_type_result_::second Chris@16: fallback_type_; Chris@16: Chris@16: struct has_fallback_type_ Chris@16: : mpl::not_< Chris@16: is_same< fallback_type_, detail::variant::no_fallback_type > Chris@16: > Chris@16: { Chris@16: }; Chris@16: Chris@16: typedef has_fallback_type_ Chris@16: never_uses_backup_flag; Chris@16: Chris@16: typedef typename detail::variant::make_storage< Chris@16: internal_types, never_uses_backup_flag Chris@16: >::type storage_t; Chris@16: Chris@16: #ifndef BOOST_NO_CXX11_NOEXCEPT Chris@101: typedef typename detail::variant::is_variant_move_noexcept_constructible< Chris@16: internal_types Chris@101: > variant_move_noexcept_constructible; Chris@101: Chris@101: typedef typename detail::variant::is_variant_move_noexcept_assignable< Chris@101: internal_types Chris@101: > variant_move_noexcept_assignable; Chris@101: Chris@16: #endif Chris@16: Chris@16: private: // helpers, for representation (below) Chris@16: Chris@16: // which_ on: Chris@16: // * [0, size) indicates stack content Chris@16: // * [-size, 0) indicates pointer to heap backup Chris@16: // if which_ >= 0: Chris@16: // * then which() -> which_ Chris@16: // * else which() -> -(which_ + 1) Chris@16: Chris@16: #if !defined(BOOST_VARIANT_MINIMIZE_SIZE) Chris@16: Chris@16: typedef int which_t; Chris@16: Chris@16: #else // defined(BOOST_VARIANT_MINIMIZE_SIZE) Chris@16: Chris@16: // [if O1_size available, then attempt which_t size optimization...] Chris@16: // [select signed char if fewer than SCHAR_MAX types, else signed int:] Chris@16: typedef typename mpl::eval_if< Chris@16: mpl::equal_to< mpl::O1_size, mpl::long_<-1> > Chris@16: , mpl::identity< int > Chris@16: , mpl::if_< Chris@16: mpl::less< mpl::O1_size, mpl::int_ > Chris@16: , signed char Chris@16: , int Chris@16: > Chris@16: >::type which_t; Chris@16: Chris@16: #endif // BOOST_VARIANT_MINIMIZE_SIZE switch Chris@16: Chris@16: // representation -- private when possible Chris@16: #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) Chris@16: private: Chris@16: #else Chris@16: public: Chris@16: #endif Chris@16: Chris@16: which_t which_; Chris@16: storage_t storage_; Chris@16: Chris@16: void indicate_which(int which_arg) BOOST_NOEXCEPT Chris@16: { Chris@16: which_ = static_cast( which_arg ); Chris@16: } Chris@16: Chris@16: void indicate_backup_which(int which_arg) BOOST_NOEXCEPT Chris@16: { Chris@16: which_ = static_cast( -(which_arg + 1) ); Chris@16: } Chris@16: Chris@16: private: // helpers, for queries (below) Chris@16: Chris@16: bool using_backup() const BOOST_NOEXCEPT Chris@16: { Chris@16: return which_ < 0; Chris@16: } Chris@16: Chris@16: public: // queries Chris@16: Chris@16: int which() const BOOST_NOEXCEPT Chris@16: { Chris@16: // If using heap backup... Chris@16: if (using_backup()) Chris@16: // ...then return adjusted which_: Chris@16: return -(which_ + 1); Chris@16: Chris@16: // Otherwise, return which_ directly: Chris@16: return which_; Chris@16: } Chris@16: Chris@16: private: // helpers, for structors (below) Chris@16: Chris@16: struct initializer Chris@16: : BOOST_VARIANT_AUX_INITIALIZER_T( Chris@16: recursive_enabled_types, recursive_enabled_T Chris@16: ) Chris@16: { Chris@16: }; Chris@16: Chris@101: void destroy_content() BOOST_NOEXCEPT Chris@16: { Chris@16: detail::variant::destroyer visitor; Chris@16: this->internal_apply_visitor(visitor); Chris@16: } Chris@16: Chris@16: public: // structors Chris@16: Chris@16: ~variant() BOOST_NOEXCEPT Chris@16: { Chris@16: destroy_content(); Chris@16: } Chris@16: Chris@101: variant() BOOST_NOEXCEPT_IF(boost::has_nothrow_constructor::value) Chris@16: { Chris@101: #ifdef _MSC_VER Chris@101: #pragma warning( push ) Chris@101: // behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized Chris@101: #pragma warning( disable : 4345 ) Chris@101: #endif Chris@16: // NOTE TO USER : Chris@16: // Compile error from here indicates that the first bound Chris@16: // type is not default-constructible, and so variant cannot Chris@16: // support its own default-construction. Chris@16: // Chris@16: new( storage_.address() ) internal_T0(); Chris@16: indicate_which(0); // zero is the index of the first bounded type Chris@101: #ifdef _MSC_VER Chris@101: #pragma warning( pop ) Chris@101: #endif Chris@16: } Chris@16: Chris@16: private: // helpers, for structors, cont. (below) Chris@16: Chris@16: class convert_copy_into Chris@16: : public static_visitor Chris@16: { Chris@16: private: // representation Chris@16: Chris@16: void* storage_; Chris@16: Chris@16: public: // structors Chris@16: Chris@16: explicit convert_copy_into(void* storage) BOOST_NOEXCEPT Chris@16: : storage_(storage) Chris@16: { Chris@16: } Chris@16: Chris@16: public: // internal visitor interfaces (below) Chris@16: Chris@16: template Chris@16: int internal_visit(T& operand, int) const Chris@16: { Chris@16: // NOTE TO USER : Chris@16: // Compile error here indicates one of the source variant's types Chris@16: // cannot be unambiguously converted to the destination variant's Chris@16: // types (or that no conversion exists). Chris@16: // Chris@16: return initializer::initialize(storage_, operand); Chris@16: } Chris@16: Chris@16: # if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564)) Chris@16: template Chris@16: result_type internal_visit(const T& operand, int) const Chris@16: { Chris@16: return initializer::initialize(storage_, operand); Chris@16: } Chris@16: # endif Chris@16: Chris@16: template Chris@16: int internal_visit(boost::detail::reference_content& operand, long) const Chris@16: { Chris@16: return internal_visit( operand.get(), 1L ); Chris@16: } Chris@16: Chris@16: template Chris@16: int internal_visit(const boost::detail::reference_content& operand, long) const Chris@16: { Chris@16: return internal_visit( operand.get(), 1L ); Chris@16: } Chris@16: Chris@16: template Chris@16: int internal_visit(boost::detail::variant::backup_holder& operand, long) const Chris@16: { Chris@16: return internal_visit( operand.get(), 1L ); Chris@16: } Chris@16: Chris@16: template Chris@16: int internal_visit(const boost::detail::variant::backup_holder& operand, long) const Chris@16: { Chris@16: return internal_visit( operand.get(), 1L ); Chris@16: } Chris@16: Chris@16: template Chris@16: int internal_visit(boost::recursive_wrapper& operand, long) const Chris@16: { Chris@16: return internal_visit( operand.get(), 1L ); Chris@16: } Chris@16: Chris@16: template Chris@16: int internal_visit(const boost::recursive_wrapper& operand, long) const Chris@16: { Chris@16: return internal_visit( operand.get(), 1L ); Chris@16: } Chris@16: Chris@16: }; Chris@16: Chris@16: friend class convert_copy_into; Chris@16: Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: class convert_move_into Chris@16: : public static_visitor Chris@16: { Chris@16: private: // representation Chris@16: Chris@16: void* storage_; Chris@16: Chris@16: public: // structors Chris@16: Chris@16: explicit convert_move_into(void* storage) BOOST_NOEXCEPT Chris@16: : storage_(storage) Chris@16: { Chris@16: } Chris@16: Chris@16: public: // internal visitor interfaces (below) Chris@16: Chris@16: template Chris@16: int internal_visit(T& operand, int) const Chris@16: { Chris@16: // NOTE TO USER : Chris@16: // Compile error here indicates one of the source variant's types Chris@16: // cannot be unambiguously converted to the destination variant's Chris@16: // types (or that no conversion exists). Chris@16: // Chris@16: return initializer::initialize(storage_, detail::variant::move(operand) ); Chris@16: } Chris@16: Chris@16: template Chris@16: int internal_visit(boost::detail::reference_content& operand, long) const Chris@16: { Chris@16: return internal_visit( operand.get(), 1L ); Chris@16: } Chris@16: Chris@16: template Chris@16: int internal_visit(const boost::detail::reference_content& operand, long) const Chris@16: { Chris@16: return internal_visit( operand.get(), 1L ); Chris@16: } Chris@16: Chris@16: template Chris@16: int internal_visit(boost::detail::variant::backup_holder& operand, long) const Chris@16: { Chris@16: return internal_visit( operand.get(), 1L ); Chris@16: } Chris@16: Chris@16: template Chris@16: int internal_visit(const boost::detail::variant::backup_holder& operand, long) const Chris@16: { Chris@16: return internal_visit( operand.get(), 1L ); Chris@16: } Chris@16: Chris@16: template Chris@16: int internal_visit(boost::recursive_wrapper& operand, long) const Chris@16: { Chris@16: return internal_visit( operand.get(), 1L ); Chris@16: } Chris@16: Chris@16: template Chris@16: int internal_visit(const boost::recursive_wrapper& operand, long) const Chris@16: { Chris@16: return internal_visit( operand.get(), 1L ); Chris@16: } Chris@16: }; Chris@16: Chris@16: friend class convert_move_into; Chris@16: #endif Chris@16: Chris@16: private: // helpers, for structors, below Chris@16: Chris@16: template Chris@16: void convert_construct( Chris@16: T& operand Chris@16: , int Chris@16: , mpl::false_ = mpl::false_() // is_foreign_variant Chris@16: ) Chris@16: { Chris@16: // NOTE TO USER : Chris@16: // Compile error here indicates that the given type is not Chris@16: // unambiguously convertible to one of the variant's types Chris@16: // (or that no conversion exists). Chris@16: // Chris@16: indicate_which( Chris@16: initializer::initialize( Chris@16: storage_.address() Chris@16: , operand Chris@16: ) Chris@16: ); Chris@16: } Chris@16: Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: template Chris@16: typename boost::enable_if >::type convert_construct( Chris@16: T&& operand Chris@16: , int Chris@16: , mpl::false_ = mpl::false_() // is_foreign_variant Chris@16: ) Chris@16: { Chris@16: // NOTE TO USER : Chris@16: // Compile error here indicates that the given type is not Chris@16: // unambiguously convertible to one of the variant's types Chris@16: // (or that no conversion exists). Chris@16: // Chris@16: indicate_which( Chris@16: initializer::initialize( Chris@16: storage_.address() Chris@16: , detail::variant::move(operand) Chris@16: ) Chris@16: ); Chris@16: } Chris@16: #endif Chris@16: Chris@16: template Chris@16: void convert_construct( Chris@16: Variant& operand Chris@16: , long Chris@16: , mpl::true_// is_foreign_variant Chris@16: ) Chris@16: { Chris@16: convert_copy_into visitor(storage_.address()); Chris@16: indicate_which( Chris@16: operand.internal_apply_visitor(visitor) Chris@16: ); Chris@16: } Chris@16: Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: template Chris@16: typename boost::enable_if >::type convert_construct( Chris@16: Variant&& operand Chris@16: , long Chris@16: , mpl::true_// is_foreign_variant Chris@16: ) Chris@16: { Chris@16: convert_move_into visitor(storage_.address()); Chris@16: indicate_which( Chris@16: operand.internal_apply_visitor(visitor) Chris@16: ); Chris@16: } Chris@16: #endif Chris@16: Chris@16: template Chris@16: void convert_construct_variant(Variant& operand) Chris@16: { Chris@16: // [Determine if the given variant is itself a bounded type, or if its Chris@16: // content needs to be converted (i.e., it is a 'foreign' variant):] Chris@16: // Chris@16: Chris@16: typedef typename mpl::find_if< Chris@16: types Chris@16: , is_same< Chris@16: add_const Chris@16: , const Variant Chris@16: > Chris@16: >::type found_it; Chris@16: Chris@16: typedef typename mpl::end::type not_found; Chris@16: typedef typename is_same< Chris@16: found_it, not_found Chris@16: >::type is_foreign_variant; Chris@16: Chris@16: // Convert construct from operand: Chris@16: convert_construct( Chris@16: operand, 1L Chris@16: , is_foreign_variant() Chris@16: ); Chris@16: } Chris@16: Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: template Chris@16: typename boost::enable_if >::type convert_construct_variant(Variant&& operand) Chris@16: { Chris@16: // [Determine if the given variant is itself a bounded type, or if its Chris@16: // content needs to be converted (i.e., it is a 'foreign' variant):] Chris@16: // Chris@16: Chris@16: typedef typename mpl::find_if< Chris@16: types Chris@16: , is_same< Chris@16: add_const Chris@16: , const Variant Chris@16: > Chris@16: >::type found_it; Chris@16: Chris@16: typedef typename mpl::end::type not_found; Chris@16: typedef typename is_same< Chris@16: found_it, not_found Chris@16: >::type is_foreign_variant; Chris@16: Chris@16: // Convert move construct from operand: Chris@16: convert_construct( Chris@16: detail::variant::move(operand), 1L Chris@16: , is_foreign_variant() Chris@16: ); Chris@16: } Chris@16: #endif Chris@16: Chris@16: template Chris@16: void convert_construct( Chris@16: boost::variant& operand Chris@16: , long Chris@16: ) Chris@16: { Chris@16: convert_construct_variant(operand); Chris@16: } Chris@16: Chris@16: template Chris@16: void convert_construct( Chris@16: const boost::variant& operand Chris@16: , long Chris@16: ) Chris@16: { Chris@16: convert_construct_variant(operand); Chris@16: } Chris@16: Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: template Chris@16: void convert_construct( Chris@16: boost::variant&& operand Chris@16: , long Chris@16: ) Chris@16: { Chris@16: convert_construct_variant( detail::variant::move(operand) ); Chris@16: } Chris@16: #endif Chris@16: Chris@16: public: // structors, cont. Chris@16: Chris@16: #if !defined(BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING) Chris@16: Chris@16: template Chris@16: variant(const T& operand) Chris@16: { Chris@16: convert_construct(operand, 1L); Chris@16: } Chris@16: Chris@16: template Chris@16: variant(T& operand) Chris@16: { Chris@16: convert_construct(operand, 1L); Chris@16: } Chris@16: Chris@16: #elif defined(BOOST_VARIANT_AUX_HAS_CONSTRUCTOR_TEMPLATE_ORDERING_SFINAE_WKND) Chris@16: Chris@16: // For compilers that cannot distinguish between T& and const T& in Chris@16: // template constructors, but do fully support SFINAE, we can workaround: Chris@16: Chris@16: template Chris@16: variant(const T& operand) Chris@16: { Chris@16: convert_construct(operand, 1L); Chris@16: } Chris@16: Chris@16: template Chris@16: variant( Chris@16: T& operand Chris@16: , typename enable_if< Chris@16: mpl::not_< is_const > Chris@16: , void Chris@16: >::type* = 0 Chris@16: ) Chris@16: { Chris@16: convert_construct(operand, 1L); Chris@16: } Chris@16: Chris@16: #else // !defined(BOOST_VARIANT_AUX_HAS_CONSTRUCTOR_TEMPLATE_ORDERING_SFINAE_WKND) Chris@16: Chris@16: // For compilers that cannot distinguish between T& and const T& in Chris@16: // template constructors, and do NOT support SFINAE, we can't workaround: Chris@16: Chris@16: template Chris@16: variant(const T& operand) Chris@16: { Chris@16: convert_construct(operand, 1L); Chris@16: } Chris@16: #endif // BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING workarounds Chris@16: Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: template Chris@16: variant(T&& operand, typename boost::enable_if >::type* = 0, Chris@16: typename boost::disable_if >::type* = 0) Chris@16: { Chris@16: convert_construct( detail::variant::move(operand), 1L); Chris@16: } Chris@16: #endif Chris@16: Chris@16: public: // structors, cont. Chris@16: Chris@16: // [MSVC6 requires copy constructor appear after template constructors] Chris@16: variant(const variant& operand) Chris@16: { Chris@16: // Copy the value of operand into *this... Chris@16: detail::variant::copy_into visitor( storage_.address() ); Chris@16: operand.internal_apply_visitor(visitor); Chris@16: Chris@16: // ...and activate the *this's primary storage on success: Chris@16: indicate_which(operand.which()); Chris@16: } Chris@16: Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@101: variant(variant&& operand) BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value) Chris@16: { Chris@16: // Move the value of operand into *this... Chris@16: detail::variant::move_into visitor( storage_.address() ); Chris@16: operand.internal_apply_visitor(visitor); Chris@16: Chris@16: // ...and activate the *this's primary storage on success: Chris@16: indicate_which(operand.which()); Chris@16: } Chris@16: #endif Chris@16: Chris@16: private: // helpers, for modifiers (below) Chris@16: Chris@16: # if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) Chris@16: template Chris@16: friend class detail::variant::backup_assigner; Chris@16: # endif Chris@16: Chris@16: // class assigner Chris@16: // Chris@16: // Internal visitor that "assigns" the visited value to the given variant Chris@16: // by appropriate destruction and copy-construction. Chris@16: // Chris@16: Chris@16: class assigner Chris@16: : public static_visitor<> Chris@16: { Chris@101: protected: // representation Chris@16: Chris@16: variant& lhs_; Chris@101: const int rhs_which_; Chris@16: Chris@16: public: // structors Chris@16: Chris@16: assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT Chris@16: : lhs_(lhs) Chris@16: , rhs_which_(rhs_which) Chris@16: { Chris@16: } Chris@16: Chris@101: protected: // helpers, for internal visitor interface (below) Chris@16: Chris@16: template Chris@16: void assign_impl( Chris@16: const RhsT& rhs_content Chris@16: , mpl::true_ // has_nothrow_copy Chris@16: , B1 // is_nothrow_move_constructible Chris@16: , B2 // has_fallback_type Chris@101: ) const BOOST_NOEXCEPT Chris@16: { Chris@16: // Destroy lhs's content... Chris@16: lhs_.destroy_content(); // nothrow Chris@16: Chris@16: // ...copy rhs content into lhs's storage... Chris@16: new(lhs_.storage_.address()) Chris@16: RhsT( rhs_content ); // nothrow Chris@16: Chris@16: // ...and indicate new content type: Chris@16: lhs_.indicate_which(rhs_which_); // nothrow Chris@16: } Chris@16: Chris@16: template Chris@16: void assign_impl( Chris@16: const RhsT& rhs_content Chris@16: , mpl::false_ // has_nothrow_copy Chris@16: , mpl::true_ // is_nothrow_move_constructible Chris@16: , B // has_fallback_type Chris@101: ) const Chris@16: { Chris@16: // Attempt to make a temporary copy (so as to move it below)... Chris@16: RhsT temp(rhs_content); Chris@16: Chris@16: // ...and upon success destroy lhs's content... Chris@16: lhs_.destroy_content(); // nothrow Chris@16: Chris@16: // ...move the temporary copy into lhs's storage... Chris@16: new(lhs_.storage_.address()) Chris@16: RhsT( detail::variant::move(temp) ); // nothrow Chris@16: Chris@16: // ...and indicate new content type: Chris@16: lhs_.indicate_which(rhs_which_); // nothrow Chris@16: } Chris@16: Chris@101: void construct_fallback() const BOOST_NOEXCEPT { Chris@101: // In case of failure, default-construct fallback type in lhs's storage... Chris@101: new (lhs_.storage_.address()) Chris@101: fallback_type_; // nothrow Chris@101: Chris@101: // ...indicate construction of fallback type... Chris@101: lhs_.indicate_which( Chris@101: BOOST_MPL_AUX_VALUE_WKND(fallback_type_index_)::value Chris@101: ); // nothrow Chris@101: } Chris@101: Chris@16: template Chris@16: void assign_impl( Chris@16: const RhsT& rhs_content Chris@16: , mpl::false_ // has_nothrow_copy Chris@16: , mpl::false_ // is_nothrow_move_constructible Chris@16: , mpl::true_ // has_fallback_type Chris@101: ) const Chris@16: { Chris@16: // Destroy lhs's content... Chris@16: lhs_.destroy_content(); // nothrow Chris@16: Chris@16: BOOST_TRY Chris@16: { Chris@16: // ...and attempt to copy rhs's content into lhs's storage: Chris@16: new(lhs_.storage_.address()) Chris@16: RhsT( rhs_content ); Chris@16: } Chris@16: BOOST_CATCH (...) Chris@16: { Chris@101: construct_fallback(); Chris@16: Chris@16: // ...and rethrow: Chris@16: BOOST_RETHROW; Chris@16: } Chris@16: BOOST_CATCH_END Chris@16: Chris@16: // In the event of success, indicate new content type: Chris@16: lhs_.indicate_which(rhs_which_); // nothrow Chris@16: } Chris@16: Chris@16: template Chris@16: void assign_impl( Chris@16: const RhsT& rhs_content Chris@16: , mpl::false_ // has_nothrow_copy Chris@16: , mpl::false_ // is_nothrow_move_constructible Chris@16: , mpl::false_ // has_fallback_type Chris@101: ) const Chris@16: { Chris@16: detail::variant::backup_assigner Chris@16: visitor(lhs_, rhs_which_, rhs_content); Chris@16: lhs_.internal_apply_visitor(visitor); Chris@16: } Chris@16: Chris@16: public: // internal visitor interfaces Chris@16: Chris@16: template Chris@16: BOOST_VARIANT_AUX_RETURN_VOID_TYPE Chris@101: internal_visit(const RhsT& rhs_content, int) const Chris@16: { Chris@16: typedef typename has_nothrow_copy::type Chris@16: nothrow_copy; Chris@16: typedef typename mpl::or_< // reduces compile-time Chris@16: nothrow_copy Chris@16: , is_nothrow_move_constructible Chris@16: >::type nothrow_move_constructor; Chris@16: Chris@16: assign_impl( Chris@16: rhs_content Chris@16: , nothrow_copy() Chris@16: , nothrow_move_constructor() Chris@16: , has_fallback_type_() Chris@16: ); Chris@16: Chris@16: BOOST_VARIANT_AUX_RETURN_VOID; Chris@16: } Chris@16: Chris@16: #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) Chris@16: private: Chris@16: // silence MSVC warning C4512: assignment operator could not be generated Chris@16: assigner& operator= (assigner const&); Chris@16: #endif Chris@16: }; Chris@16: Chris@16: friend class assigner; Chris@16: Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: // class move_assigner Chris@16: // Chris@16: // Internal visitor that "move assigns" the visited value to the given variant Chris@16: // by appropriate destruction and move-construction. Chris@16: // Chris@16: Chris@16: class move_assigner Chris@101: : public assigner Chris@16: { Chris@16: public: // structors Chris@16: Chris@16: move_assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT Chris@101: : assigner(lhs, rhs_which) Chris@16: { Chris@16: } Chris@16: Chris@16: private: // helpers, for internal visitor interface (below) Chris@101: Chris@16: template Chris@16: void assign_impl( Chris@16: RhsT& rhs_content Chris@16: , mpl::true_ // has_nothrow_copy Chris@16: , mpl::false_ // is_nothrow_move_constructible Chris@16: , B2 // has_fallback_type Chris@101: ) const BOOST_NOEXCEPT Chris@16: { Chris@101: assigner::assign_impl(rhs_content, mpl::true_(), mpl::false_(), B2()); Chris@16: } Chris@16: Chris@101: template Chris@16: void assign_impl( Chris@16: RhsT& rhs_content Chris@101: , B // has_nothrow_copy Chris@16: , mpl::true_ // is_nothrow_move_constructible Chris@101: , B2 // has_fallback_type Chris@101: ) const BOOST_NOEXCEPT Chris@16: { Chris@16: // ...destroy lhs's content... Chris@101: assigner::lhs_.destroy_content(); // nothrow Chris@16: Chris@16: // ...move the rhs_content into lhs's storage... Chris@101: new(assigner::lhs_.storage_.address()) Chris@16: RhsT( detail::variant::move(rhs_content) ); // nothrow Chris@16: Chris@16: // ...and indicate new content type: Chris@101: assigner::lhs_.indicate_which(assigner::rhs_which_); // nothrow Chris@16: } Chris@16: Chris@16: template Chris@16: void assign_impl( Chris@16: RhsT& rhs_content Chris@16: , mpl::false_ // has_nothrow_copy Chris@16: , mpl::false_ // is_nothrow_move_constructible Chris@16: , mpl::true_ // has_fallback_type Chris@101: ) const Chris@16: { Chris@16: // Destroy lhs's content... Chris@101: assigner::lhs_.destroy_content(); // nothrow Chris@16: Chris@16: BOOST_TRY Chris@16: { Chris@16: // ...and attempt to copy rhs's content into lhs's storage: Chris@101: new(assigner::lhs_.storage_.address()) Chris@16: RhsT( detail::variant::move(rhs_content) ); Chris@16: } Chris@16: BOOST_CATCH (...) Chris@16: { Chris@101: assigner::construct_fallback(); Chris@16: Chris@16: // ...and rethrow: Chris@16: BOOST_RETHROW; Chris@16: } Chris@16: BOOST_CATCH_END Chris@16: Chris@16: // In the event of success, indicate new content type: Chris@101: assigner::lhs_.indicate_which(assigner::rhs_which_); // nothrow Chris@16: } Chris@101: Chris@16: template Chris@16: void assign_impl( Chris@101: RhsT& rhs_content Chris@16: , mpl::false_ // has_nothrow_copy Chris@16: , mpl::false_ // is_nothrow_move_constructible Chris@16: , mpl::false_ // has_fallback_type Chris@101: ) const Chris@16: { Chris@101: assigner::assign_impl(rhs_content, mpl::false_(), mpl::false_(), mpl::false_()); Chris@16: } Chris@16: Chris@16: public: // internal visitor interfaces Chris@16: Chris@16: template Chris@16: BOOST_VARIANT_AUX_RETURN_VOID_TYPE Chris@101: internal_visit(RhsT& rhs_content, int) const Chris@16: { Chris@16: typedef typename is_nothrow_move_constructible::type Chris@16: nothrow_move_constructor; Chris@16: typedef typename mpl::or_< // reduces compile-time Chris@16: nothrow_move_constructor Chris@16: , has_nothrow_copy Chris@16: >::type nothrow_copy; Chris@16: Chris@16: assign_impl( Chris@16: rhs_content Chris@16: , nothrow_copy() Chris@16: , nothrow_move_constructor() Chris@16: , has_fallback_type_() Chris@16: ); Chris@16: Chris@16: BOOST_VARIANT_AUX_RETURN_VOID; Chris@16: } Chris@16: Chris@16: #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) Chris@16: private: Chris@16: // silence MSVC warning C4512: assignment operator could not be generated Chris@16: move_assigner& operator= (move_assigner const&); Chris@16: #endif Chris@16: }; Chris@16: Chris@16: friend class move_assigner; Chris@16: #endif // BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: Chris@16: void variant_assign(const variant& rhs) Chris@16: { Chris@16: // If the contained types are EXACTLY the same... Chris@16: if (which_ == rhs.which_) Chris@16: { Chris@16: // ...then assign rhs's storage to lhs's content: Chris@16: detail::variant::assign_storage visitor(rhs.storage_.address()); Chris@16: this->internal_apply_visitor(visitor); Chris@16: } Chris@16: else Chris@16: { Chris@16: // Otherwise, perform general (copy-based) variant assignment: Chris@16: assigner visitor(*this, rhs.which()); Chris@16: rhs.internal_apply_visitor(visitor); Chris@16: } Chris@16: } Chris@16: Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: void variant_assign(variant&& rhs) Chris@16: { Chris@16: // If the contained types are EXACTLY the same... Chris@16: if (which_ == rhs.which_) Chris@16: { Chris@16: // ...then move rhs's storage to lhs's content: Chris@16: detail::variant::move_storage visitor(rhs.storage_.address()); Chris@16: this->internal_apply_visitor(visitor); Chris@16: } Chris@16: else Chris@16: { Chris@16: // Otherwise, perform general (move-based) variant assignment: Chris@16: move_assigner visitor(*this, rhs.which()); Chris@16: rhs.internal_apply_visitor(visitor); Chris@16: } Chris@16: } Chris@16: #endif // BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: Chris@16: private: // helpers, for modifiers (below) Chris@16: Chris@16: template Chris@16: void assign(const T& rhs) Chris@16: { Chris@16: // If direct T-to-T assignment is not possible... Chris@16: detail::variant::direct_assigner direct_assign(rhs); Chris@16: if (this->apply_visitor(direct_assign) == false) Chris@16: { Chris@16: // ...then convert rhs to variant and assign: Chris@16: // Chris@16: // While potentially inefficient, the following construction of a Chris@16: // variant allows T as any type convertible to one of the bounded Chris@16: // types without excessive code redundancy. Chris@16: // Chris@16: variant temp(rhs); Chris@16: variant_assign( detail::variant::move(temp) ); Chris@16: } Chris@16: } Chris@16: Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: template Chris@16: void move_assign(T&& rhs) Chris@16: { Chris@16: // If direct T-to-T move assignment is not possible... Chris@16: detail::variant::direct_mover direct_move(rhs); Chris@16: if (this->apply_visitor(direct_move) == false) Chris@16: { Chris@16: // ...then convert rhs to variant and assign: Chris@16: // Chris@16: // While potentially inefficient, the following construction of a Chris@16: // variant allows T as any type convertible to one of the bounded Chris@16: // types without excessive code redundancy. Chris@16: // Chris@16: variant temp( detail::variant::move(rhs) ); Chris@16: variant_assign( detail::variant::move(temp) ); Chris@16: } Chris@16: } Chris@16: #endif // BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: Chris@16: public: // modifiers Chris@16: Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: template Chris@16: typename boost::enable_if_c::value && !boost::is_const::value, variant& >::type Chris@101: operator=(T&& rhs) Chris@16: { Chris@16: move_assign( detail::variant::move(rhs) ); Chris@16: return *this; Chris@16: } Chris@16: #endif // BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: Chris@16: template Chris@16: variant& operator=(const T& rhs) Chris@16: { Chris@16: assign(rhs); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: // [MSVC6 requires copy assign appear after templated operator=] Chris@16: variant& operator=(const variant& rhs) Chris@16: { Chris@16: variant_assign(rhs); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@101: variant& operator=(variant&& rhs) Chris@101: #if !defined(__GNUC__) || (__GNUC__ != 4) || (__GNUC_MINOR__ > 6) Chris@101: BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value && variant_move_noexcept_assignable::type::value) Chris@101: #endif Chris@16: { Chris@16: variant_assign( detail::variant::move(rhs) ); Chris@16: return *this; Chris@16: } Chris@16: #endif // BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: Chris@16: void swap(variant& rhs) Chris@16: { Chris@16: // If the contained types are the same... Chris@16: if (which() == rhs.which()) Chris@16: { Chris@16: // ...then swap the values directly: Chris@16: detail::variant::swap_with visitor(rhs); Chris@16: this->apply_visitor(visitor); Chris@16: } Chris@16: else Chris@16: { Chris@16: // ...otherwise, perform general variant swap: Chris@16: variant tmp( detail::variant::move(rhs) ); Chris@16: rhs = detail::variant::move(*this); Chris@16: *this = detail::variant::move(tmp); Chris@16: } Chris@16: } Chris@16: Chris@16: public: // queries Chris@16: Chris@16: // Chris@16: // NOTE: member which() defined above. Chris@16: // Chris@16: Chris@16: bool empty() const BOOST_NOEXCEPT Chris@16: { Chris@16: return false; Chris@16: } Chris@16: Chris@101: const boost::typeindex::type_info& type() const Chris@16: { Chris@16: detail::variant::reflect visitor; Chris@16: return this->apply_visitor(visitor); Chris@16: } Chris@16: Chris@16: public: // prevent comparison with foreign types Chris@16: Chris@101: // Obsolete. Remove. Chris@16: # define BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE \ Chris@16: void Chris@16: Chris@16: template Chris@101: void operator==(const U&) const Chris@16: { Chris@16: BOOST_STATIC_ASSERT( false && sizeof(U) ); Chris@16: } Chris@16: Chris@16: template Chris@101: void operator<(const U&) const Chris@101: { Chris@101: BOOST_STATIC_ASSERT( false && sizeof(U) ); Chris@101: } Chris@101: Chris@101: template Chris@101: void operator!=(const U&) const Chris@101: { Chris@101: BOOST_STATIC_ASSERT( false && sizeof(U) ); Chris@101: } Chris@101: Chris@101: template Chris@101: void operator>(const U&) const Chris@101: { Chris@101: BOOST_STATIC_ASSERT( false && sizeof(U) ); Chris@101: } Chris@101: Chris@101: template Chris@101: void operator<=(const U&) const Chris@101: { Chris@101: BOOST_STATIC_ASSERT( false && sizeof(U) ); Chris@101: } Chris@101: Chris@101: template Chris@101: void operator>=(const U&) const Chris@16: { Chris@16: BOOST_STATIC_ASSERT( false && sizeof(U) ); Chris@16: } Chris@16: Chris@16: public: // comparison operators Chris@16: Chris@16: // [MSVC6 requires these operators appear after template operators] Chris@16: Chris@16: bool operator==(const variant& rhs) const Chris@16: { Chris@16: if (this->which() != rhs.which()) Chris@16: return false; Chris@16: Chris@16: detail::variant::comparer< Chris@16: variant, detail::variant::equal_comp Chris@16: > visitor(*this); Chris@16: return rhs.apply_visitor(visitor); Chris@16: } Chris@16: Chris@16: bool operator<(const variant& rhs) const Chris@16: { Chris@16: // Chris@16: // Dirk Schreib suggested this collating order. Chris@16: // Chris@16: Chris@16: if (this->which() != rhs.which()) Chris@16: return this->which() < rhs.which(); Chris@16: Chris@16: detail::variant::comparer< Chris@16: variant, detail::variant::less_comp Chris@16: > visitor(*this); Chris@16: return rhs.apply_visitor(visitor); Chris@16: } Chris@16: Chris@101: /////////////////////////////////////////////////////////////////////////////// Chris@101: // comparison operators != > <= >= Chris@101: inline bool operator!=(const variant& rhs) const Chris@101: { Chris@101: return !(*this == rhs); Chris@101: } Chris@101: Chris@101: inline bool operator>(const variant& rhs) const Chris@101: { Chris@101: return rhs < *this; Chris@101: } Chris@101: Chris@101: inline bool operator<=(const variant& rhs) const Chris@101: { Chris@101: return !(*this > rhs); Chris@101: } Chris@101: Chris@101: inline bool operator>=(const variant& rhs) const Chris@101: { Chris@101: return !(*this < rhs); Chris@101: } Chris@101: Chris@16: // helpers, for visitation support (below) -- private when possible Chris@16: #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) Chris@16: Chris@16: template < BOOST_VARIANT_ENUM_PARAMS(typename U) > Chris@16: friend class variant; Chris@16: Chris@16: private: Chris@16: Chris@16: #else// defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) Chris@16: Chris@16: public: Chris@16: Chris@16: #endif// !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) Chris@16: Chris@16: template Chris@16: static Chris@16: BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE( Chris@16: typename Visitor::result_type Chris@16: ) Chris@16: internal_apply_visitor_impl( Chris@16: int internal_which Chris@16: , int logical_which Chris@16: , Visitor& visitor Chris@16: , VoidPtrCV storage Chris@16: ) Chris@16: { Chris@16: typedef mpl::int_<0> first_which; Chris@16: typedef typename mpl::begin::type first_it; Chris@16: typedef typename mpl::end::type last_it; Chris@16: Chris@16: typedef detail::variant::visitation_impl_step< Chris@16: first_it, last_it Chris@16: > first_step; Chris@16: Chris@16: return detail::variant::visitation_impl( Chris@16: internal_which, logical_which Chris@16: , visitor, storage, mpl::false_() Chris@16: , never_uses_backup_flag() Chris@16: , static_cast(0), static_cast(0) Chris@16: ); Chris@16: } Chris@16: Chris@16: template Chris@16: BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE( Chris@16: typename Visitor::result_type Chris@16: ) Chris@16: internal_apply_visitor(Visitor& visitor) Chris@16: { Chris@16: return internal_apply_visitor_impl( Chris@16: which_, which(), visitor, storage_.address() Chris@16: ); Chris@16: } Chris@16: Chris@16: template Chris@16: BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE( Chris@16: typename Visitor::result_type Chris@16: ) Chris@16: internal_apply_visitor(Visitor& visitor) const Chris@16: { Chris@16: return internal_apply_visitor_impl( Chris@16: which_, which(), visitor, storage_.address() Chris@16: ); Chris@16: } Chris@16: Chris@16: public: // visitation support Chris@16: Chris@16: template Chris@16: BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE( Chris@16: typename Visitor::result_type Chris@16: ) Chris@16: apply_visitor(Visitor& visitor) Chris@16: { Chris@16: detail::variant::invoke_visitor invoker(visitor); Chris@16: return this->internal_apply_visitor(invoker); Chris@16: } Chris@16: Chris@16: template Chris@16: BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE( Chris@16: typename Visitor::result_type Chris@16: ) Chris@16: apply_visitor(Visitor& visitor) const Chris@16: { Chris@16: detail::variant::invoke_visitor invoker(visitor); Chris@16: return this->internal_apply_visitor(invoker); Chris@16: } Chris@16: Chris@16: }; // class variant Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // metafunction make_variant_over Chris@16: // Chris@16: // See docs and boost/variant/variant_fwd.hpp for more information. Chris@16: // Chris@16: template Chris@16: struct make_variant_over Chris@16: { Chris@16: private: // precondition assertions Chris@16: Chris@16: BOOST_STATIC_ASSERT(( ::boost::mpl::is_sequence::value )); Chris@16: Chris@16: public: // metafunction result Chris@16: Chris@16: typedef variant< Chris@16: detail::variant::over_sequence< Types > Chris@16: > type; Chris@16: Chris@16: }; Chris@16: Chris@101: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // function template swap Chris@16: // Chris@16: // Swaps two variants of the same type (i.e., identical specification). Chris@16: // Chris@16: template < BOOST_VARIANT_ENUM_PARAMS(typename T) > Chris@16: inline void swap( Chris@16: variant< BOOST_VARIANT_ENUM_PARAMS(T) >& lhs Chris@16: , variant< BOOST_VARIANT_ENUM_PARAMS(T) >& rhs Chris@16: ) Chris@16: { Chris@16: lhs.swap(rhs); Chris@16: } Chris@16: Chris@16: } // namespace boost Chris@16: Chris@16: // implementation additions Chris@16: Chris@16: #if !defined(BOOST_NO_IOSTREAM) Chris@16: #include "boost/variant/detail/variant_io.hpp" Chris@16: #endif // BOOST_NO_IOSTREAM Chris@16: Chris@16: #endif // BOOST_VARIANT_VARIANT_HPP