summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '3rdParty/Boost/src/boost/variant/variant.hpp')
-rw-r--r--3rdParty/Boost/src/boost/variant/variant.hpp784
1 files changed, 612 insertions, 172 deletions
diff --git a/3rdParty/Boost/src/boost/variant/variant.hpp b/3rdParty/Boost/src/boost/variant/variant.hpp
index 6afd190..4ed5ad4 100644
--- a/3rdParty/Boost/src/boost/variant/variant.hpp
+++ b/3rdParty/Boost/src/boost/variant/variant.hpp
@@ -3,13 +3,15 @@
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
-// Copyright (c) 2002-2003
-// Eric Friedman, Itay Maman
+// Copyright (c) 2002-2003 Eric Friedman, Itay Maman
+// Copyright (c) 2012-2013 Antony Polukhin
//
// 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)
+// Thanks to Adam Romanek for providing patches for exception-disabled env.
+
#ifndef BOOST_VARIANT_VARIANT_HPP
#define BOOST_VARIANT_VARIANT_HPP
@@ -21,7 +23,6 @@
#endif // BOOST_NO_TYPEID
#include "boost/variant/detail/config.hpp"
-#include "boost/mpl/aux_/config/eti.hpp"
#include "boost/mpl/aux_/value_wknd.hpp"
#include "boost/variant/variant_fwd.hpp"
@@ -35,9 +36,9 @@
#include "boost/variant/detail/hash_variant.hpp"
#include "boost/variant/detail/generic_result_type.hpp"
-#include "boost/variant/detail/has_nothrow_move.hpp"
#include "boost/variant/detail/move.hpp"
+#include "boost/detail/no_exceptions_support.hpp"
#include "boost/detail/reference_content.hpp"
#include "boost/aligned_storage.hpp"
#include "boost/blank.hpp"
@@ -49,9 +50,12 @@
#include "boost/type_traits/add_const.hpp"
#include "boost/type_traits/has_nothrow_constructor.hpp"
#include "boost/type_traits/has_nothrow_copy.hpp"
+#include "boost/type_traits/is_nothrow_move_constructible.hpp"
#include "boost/type_traits/is_const.hpp"
#include "boost/type_traits/is_same.hpp"
+#include "boost/type_traits/is_rvalue_reference.hpp"
#include "boost/utility/enable_if.hpp"
+#include "boost/utility/declval.hpp"
#include "boost/variant/recursive_wrapper_fwd.hpp"
#include "boost/variant/static_visitor.hpp"
@@ -214,15 +218,41 @@ public: // metafunction result
};
-#if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG)
-
-template<>
-struct find_fallback_type<int>
-{
- typedef mpl::pair< no_fallback_type,no_fallback_type > type;
+#ifndef BOOST_NO_CXX11_NOEXCEPT
+///////////////////////////////////////////////////////////////////////////////
+// (detail) metafunction is_variant_move_noexcept_constructible
+//
+// Returns true_type if all the types are nothrow move constructible.
+//
+template <class Types>
+struct is_variant_move_noexcept_constructible {
+ typedef typename boost::mpl::find_if<
+ Types, mpl::not_<boost::is_nothrow_move_constructible<boost::mpl::_1> >
+ >::type iterator_t;
+
+ typedef typename boost::mpl::end<Types>::type end_t;
+ typedef typename boost::is_same<
+ iterator_t, end_t
+ >::type type;
};
-#endif // BOOST_MPL_CFG_MSVC_60_ETI_BUG workaround
+///////////////////////////////////////////////////////////////////////////////
+// (detail) metafunction is_variant_move_noexcept_assignable
+//
+// Returns true_type if all the types are nothrow move constructible.
+//
+template <class Types>
+struct is_variant_move_noexcept_assignable {
+ typedef typename boost::mpl::find_if<
+ Types, mpl::not_<boost::is_nothrow_move_assignable<boost::mpl::_1> >
+ >::type iterator_t;
+
+ typedef typename boost::mpl::end<Types>::type end_t;
+ typedef typename boost::is_same<
+ iterator_t, end_t
+ >::type type;
+};
+#endif // BOOST_NO_CXX11_NOEXCEPT
///////////////////////////////////////////////////////////////////////////////
// (detail) metafunction make_storage
@@ -265,37 +295,12 @@ private: // helpers, for metafunction result (below)
public: // metafunction result
-#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
-
typedef ::boost::aligned_storage<
BOOST_MPL_AUX_VALUE_WKND(max_size)::value
, BOOST_MPL_AUX_VALUE_WKND(max_alignment)::value
> type;
-
-#else // MSVC7 and below
-
- BOOST_STATIC_CONSTANT(std::size_t, msvc_max_size_c = max_size::value);
- BOOST_STATIC_CONSTANT(std::size_t, msvc_max_alignment_c = max_alignment::value);
-
- typedef ::boost::aligned_storage<
- msvc_max_size_c
- , msvc_max_alignment_c
- > type;
-
-#endif // MSVC workaround
-
};
-#if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG)
-
-template<>
-struct make_storage<int,int>
-{
- typedef int type;
-};
-
-#endif // BOOST_MPL_CFG_MSVC_60_ETI_BUG workaround
-
///////////////////////////////////////////////////////////////////////////////
// (detail) class destroyer
//
@@ -308,9 +313,9 @@ public: // visitor interfaces
template <typename T>
BOOST_VARIANT_AUX_RETURN_VOID_TYPE
- internal_visit(T& operand, int) const
+ internal_visit(T& operand, int) const BOOST_NOEXCEPT
{
- operand.~T();
+ operand.~T(); // must be noexcept
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551)) || \
BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
@@ -334,11 +339,9 @@ class known_get
: public static_visitor<T&>
{
-#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
-
public: // visitor interface
- T& operator()(T& operand) const
+ T& operator()(T& operand) const BOOST_NOEXCEPT
{
return operand;
}
@@ -347,40 +350,8 @@ public: // visitor interface
T& operator()(U&) const
{
// logical error to be here: see precondition above
- BOOST_ASSERT(false);
return ::boost::detail::variant::forced_return< T& >();
}
-
-#else // MSVC6
-
-private: // helpers, for visitor interface (below)
-
- T& execute(T& operand, mpl::true_) const
- {
- return operand;
- }
-
- template <typename U>
- T& execute(U& operand, mpl::false_) const
- {
- // logical error to be here: see precondition above
- BOOST_ASSERT(false);
- return ::boost::detail::variant::forced_return< T& >();
- }
-
-public: // visitor interface
-
- template <typename U>
- T& operator()(U& operand) const
- {
- typedef typename is_same< U,T >::type
- U_is_T;
-
- return execute(operand, U_is_T());
- }
-
-#endif // MSVC6 workaround
-
};
///////////////////////////////////////////////////////////////////////////////
@@ -397,7 +368,7 @@ private: // representation
public: // structors
- explicit copy_into(void* storage)
+ explicit copy_into(void* storage) BOOST_NOEXCEPT
: storage_(storage)
{
}
@@ -431,6 +402,46 @@ public: // internal visitor interface
};
///////////////////////////////////////////////////////////////////////////////
+// (detail) class move_into
+//
+// Internal visitor that moves the value it visits into the given buffer.
+//
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+class move_into
+ : public static_visitor<>
+{
+private: // representation
+
+ void* storage_;
+
+public: // structors
+
+ explicit move_into(void* storage) BOOST_NOEXCEPT
+ : storage_(storage)
+ {
+ }
+
+public: // internal visitor interface
+
+ template <typename T>
+ BOOST_VARIANT_AUX_RETURN_VOID_TYPE
+ internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
+ {
+ new(storage_) T( ::boost::detail::variant::move(operand.get()) );
+ BOOST_VARIANT_AUX_RETURN_VOID;
+ }
+
+ template <typename T>
+ BOOST_VARIANT_AUX_RETURN_VOID_TYPE
+ internal_visit(T& operand, int) const BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T(boost::declval<T>())))
+ {
+ new(storage_) T(::boost::detail::variant::move(operand));
+ BOOST_VARIANT_AUX_RETURN_VOID;
+ }
+};
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
// (detail) class assign_storage
//
// Internal visitor that assigns the given storage (which must be a
@@ -445,7 +456,7 @@ private: // representation
public: // structors
- explicit assign_storage(const void* rhs_storage)
+ explicit assign_storage(const void* rhs_storage) BOOST_NOEXCEPT
: rhs_storage_(rhs_storage)
{
}
@@ -488,6 +499,63 @@ public: // internal visitor interfaces
};
///////////////////////////////////////////////////////////////////////////////
+// (detail) class move_storage
+//
+// Internal visitor that moves the given storage (which must be a
+// constructed value of the same type) to the value it visits.
+//
+struct move_storage
+ : public static_visitor<>
+{
+private: // representation
+
+ void* rhs_storage_;
+
+public: // structors
+
+ explicit move_storage(void* rhs_storage) BOOST_NOEXCEPT
+ : rhs_storage_(rhs_storage)
+ {
+ }
+
+public: // internal visitor interfaces
+
+ template <typename T>
+ BOOST_VARIANT_AUX_RETURN_VOID_TYPE
+ internal_visit(backup_holder<T>& lhs_content, long) const
+ {
+ lhs_content.get()
+ = ::boost::detail::variant::move(static_cast<backup_holder<T>* >(rhs_storage_)->get());
+ BOOST_VARIANT_AUX_RETURN_VOID;
+ }
+
+ template <typename T>
+ BOOST_VARIANT_AUX_RETURN_VOID_TYPE
+ internal_visit(const backup_holder<T>& lhs_content, long) const
+ {
+ lhs_content.get()
+ = ::boost::detail::variant::move(static_cast<backup_holder<T>* >(rhs_storage_)->get());
+ BOOST_VARIANT_AUX_RETURN_VOID;
+ }
+
+ template <typename T>
+ BOOST_VARIANT_AUX_RETURN_VOID_TYPE
+ internal_visit(T& lhs_content, int) const
+ {
+ // NOTE TO USER :
+ // Compile error here indicates one of variant's bounded types does
+ // not meet the requirements of the Assignable concept. Thus,
+ // variant is not Assignable.
+ //
+ // Hint: Are any of the bounded types const-qualified or references?
+ //
+ lhs_content = ::boost::detail::variant::move(*static_cast<T* >(rhs_storage_));
+ BOOST_VARIANT_AUX_RETURN_VOID;
+ }
+
+};
+
+///////////////////////////////////////////////////////////////////////////////
// (detail) class direct_assigner
//
// Generic static visitor that: if and only if the visited value is of the
@@ -504,13 +572,11 @@ private: // representation
public: // structors
- explicit direct_assigner(const T& rhs)
+ explicit direct_assigner(const T& rhs) BOOST_NOEXCEPT
: rhs_(rhs)
{
}
-#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
-
public: // visitor interface
bool operator()(T& lhs)
@@ -520,45 +586,62 @@ public: // visitor interface
}
template <typename U>
- bool operator()(U&)
+ bool operator()(U&) BOOST_NOEXCEPT
{
return false;
}
-#else // MSVC6
+#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
+private:
+ // silence MSVC warning C4512: assignment operator could not be generated
+ direct_assigner& operator= (direct_assigner const&);
+#endif
+};
-private: // helpers, for visitor interface (below)
+///////////////////////////////////////////////////////////////////////////////
+// (detail) class direct_mover
+//
+// Generic static visitor that: if and only if the visited value is of the
+// specified type, move assigns the given value to the visited value and returns
+// true; else returns false.
+//
+template <typename T>
+class direct_mover
+ : public static_visitor<bool>
+{
+private: // representation
- bool execute(T& lhs, mpl::true_)
- {
- lhs = rhs_;
- return true;
- }
+ T& rhs_;
- template <typename U>
- bool execute(U&, mpl::false_)
+public: // structors
+
+ explicit direct_mover(T& rhs) BOOST_NOEXCEPT
+ : rhs_(rhs)
{
- return false;
}
public: // visitor interface
- template <typename U>
- bool operator()(U& lhs)
+ bool operator()(T& lhs)
{
- typedef typename is_same<U,T>::type U_is_T;
- return execute(lhs, U_is_T());
+ lhs = ::boost::detail::variant::move(rhs_);
+ return true;
}
-#endif // MSVC6 workaround
+ template <typename U>
+ bool operator()(U&) BOOST_NOEXCEPT
+ {
+ return false;
+ }
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
private:
// silence MSVC warning C4512: assignment operator could not be generated
- direct_assigner& operator= (direct_assigner const&);
+ direct_mover& operator= (direct_mover const&);
#endif
};
+
///////////////////////////////////////////////////////////////////////////////
// (detail) class backup_assigner
//
@@ -601,7 +684,7 @@ private: // helpers, for visitor interface (below)
template <typename LhsT>
void backup_assign_impl(
LhsT& lhs_content
- , mpl::true_// has_nothrow_move
+ , mpl::true_ // is_nothrow_move_constructible
)
{
// Move lhs content to backup...
@@ -612,12 +695,12 @@ private: // helpers, for visitor interface (below)
// ...destroy lhs content...
lhs_content.~LhsT(); // nothrow
- try
+ BOOST_TRY
{
// ...and attempt to copy rhs content into lhs storage:
copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
}
- catch (...)
+ BOOST_CATCH (...)
{
// In case of failure, restore backup content to lhs storage...
new(lhs_.storage_.address())
@@ -626,8 +709,9 @@ private: // helpers, for visitor interface (below)
); // nothrow
// ...and rethrow:
- throw;
+ BOOST_RETHROW;
}
+ BOOST_CATCH_END
// In case of success, indicate new content type:
lhs_.indicate_which(rhs_which_); // nothrow
@@ -636,7 +720,7 @@ private: // helpers, for visitor interface (below)
template <typename LhsT>
void backup_assign_impl(
LhsT& lhs_content
- , mpl::false_// has_nothrow_move
+ , mpl::false_ // is_nothrow_move_constructible
)
{
// Backup lhs content...
@@ -645,12 +729,12 @@ private: // helpers, for visitor interface (below)
// ...destroy lhs content...
lhs_content.~LhsT(); // nothrow
- try
+ BOOST_TRY
{
// ...and attempt to copy rhs content into lhs storage:
copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
}
- catch (...)
+ BOOST_CATCH (...)
{
// In case of failure, copy backup pointer to lhs storage...
new(lhs_.storage_.address())
@@ -660,8 +744,9 @@ private: // helpers, for visitor interface (below)
lhs_.indicate_backup_which( lhs_.which() ); // nothrow
// ...and rethrow:
- throw;
+ BOOST_RETHROW;
}
+ BOOST_CATCH_END
// In case of success, indicate new content type...
lhs_.indicate_which(rhs_which_); // nothrow
@@ -676,7 +761,7 @@ public: // visitor interface
BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visit(LhsT& lhs_content, int)
{
- typedef typename has_nothrow_move_constructor<LhsT>::type
+ typedef typename is_nothrow_move_constructible<LhsT>::type
nothrow_move;
backup_assign_impl( lhs_content, nothrow_move() );
@@ -708,7 +793,7 @@ private: // representation
public: // structors
- explicit swap_with(Variant& toswap)
+ explicit swap_with(Variant& toswap) BOOST_NOEXCEPT
: toswap_(toswap)
{
}
@@ -745,7 +830,7 @@ class reflect
public: // visitor interfaces
template <typename T>
- const std::type_info& operator()(const T&) const
+ const std::type_info& operator()(const T&) const BOOST_NOEXCEPT
{
return typeid(T);
}
@@ -772,7 +857,7 @@ private: // representation
public: // structors
- explicit comparer(const Variant& lhs)
+ explicit comparer(const Variant& lhs) BOOST_NOEXCEPT
: lhs_(lhs)
{
}
@@ -844,7 +929,7 @@ public: // visitor typedefs
public: // structors
- explicit invoke_visitor(Visitor& visitor)
+ explicit invoke_visitor(Visitor& visitor) BOOST_NOEXCEPT
: visitor_(visitor)
{
}
@@ -1131,6 +1216,17 @@ private: // helpers, for representation (below)
internal_types, never_uses_backup_flag
>::type storage_t;
+#ifndef BOOST_NO_CXX11_NOEXCEPT
+ typedef typename detail::variant::is_variant_move_noexcept_constructible<
+ internal_types
+ > variant_move_noexcept_constructible;
+
+ typedef typename detail::variant::is_variant_move_noexcept_assignable<
+ internal_types
+ > variant_move_noexcept_assignable;
+
+#endif
+
private: // helpers, for representation (below)
// which_ on:
@@ -1170,26 +1266,26 @@ private: // helpers, for representation (below)
which_t which_;
storage_t storage_;
- void indicate_which(int which_arg)
+ void indicate_which(int which_arg) BOOST_NOEXCEPT
{
which_ = static_cast<which_t>( which_arg );
}
- void indicate_backup_which(int which_arg)
+ void indicate_backup_which(int which_arg) BOOST_NOEXCEPT
{
which_ = static_cast<which_t>( -(which_arg + 1) );
}
private: // helpers, for queries (below)
- bool using_backup() const
+ bool using_backup() const BOOST_NOEXCEPT
{
return which_ < 0;
}
public: // queries
- int which() const
+ int which() const BOOST_NOEXCEPT
{
// If using heap backup...
if (using_backup())
@@ -1209,7 +1305,7 @@ private: // helpers, for structors (below)
{
};
- void destroy_content()
+ void destroy_content() BOOST_NOEXCEPT
{
detail::variant::destroyer visitor;
this->internal_apply_visitor(visitor);
@@ -1217,13 +1313,18 @@ private: // helpers, for structors (below)
public: // structors
- ~variant()
+ ~variant() BOOST_NOEXCEPT
{
destroy_content();
}
- variant()
+ variant() BOOST_NOEXCEPT_IF(boost::has_nothrow_constructor<internal_T0>::value)
{
+#ifdef _MSC_VER
+#pragma warning( push )
+// behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized
+#pragma warning( disable : 4345 )
+#endif
// NOTE TO USER :
// Compile error from here indicates that the first bound
// type is not default-constructible, and so variant cannot
@@ -1231,6 +1332,9 @@ public: // structors
//
new( storage_.address() ) internal_T0();
indicate_which(0); // zero is the index of the first bounded type
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
}
private: // helpers, for structors, cont. (below)
@@ -1244,7 +1348,7 @@ private: // helpers, for structors, cont. (below)
public: // structors
- explicit convert_copy_into(void* storage)
+ explicit convert_copy_into(void* storage) BOOST_NOEXCEPT
: storage_(storage)
{
}
@@ -1310,6 +1414,74 @@ private: // helpers, for structors, cont. (below)
friend class convert_copy_into;
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ class convert_move_into
+ : public static_visitor<int>
+ {
+ private: // representation
+
+ void* storage_;
+
+ public: // structors
+
+ explicit convert_move_into(void* storage) BOOST_NOEXCEPT
+ : storage_(storage)
+ {
+ }
+
+ public: // internal visitor interfaces (below)
+
+ template <typename T>
+ int internal_visit(T& operand, int) const
+ {
+ // NOTE TO USER :
+ // Compile error here indicates one of the source variant's types
+ // cannot be unambiguously converted to the destination variant's
+ // types (or that no conversion exists).
+ //
+ return initializer::initialize(storage_, detail::variant::move(operand) );
+ }
+
+ template <typename T>
+ int internal_visit(boost::detail::reference_content<T>& operand, long) const
+ {
+ return internal_visit( operand.get(), 1L );
+ }
+
+ template <typename T>
+ int internal_visit(const boost::detail::reference_content<T>& operand, long) const
+ {
+ return internal_visit( operand.get(), 1L );
+ }
+
+ template <typename T>
+ int internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
+ {
+ return internal_visit( operand.get(), 1L );
+ }
+
+ template <typename T>
+ int internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
+ {
+ return internal_visit( operand.get(), 1L );
+ }
+
+ template <typename T>
+ int internal_visit(boost::recursive_wrapper<T>& operand, long) const
+ {
+ return internal_visit( operand.get(), 1L );
+ }
+
+ template <typename T>
+ int internal_visit(const boost::recursive_wrapper<T>& operand, long) const
+ {
+ return internal_visit( operand.get(), 1L );
+ }
+ };
+
+ friend class convert_move_into;
+#endif
+
private: // helpers, for structors, below
template <typename T>
@@ -1332,6 +1504,28 @@ private: // helpers, for structors, below
);
}
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template <typename T>
+ typename boost::enable_if<boost::is_rvalue_reference<T&&> >::type convert_construct(
+ T&& operand
+ , int
+ , mpl::false_ = mpl::false_() // is_foreign_variant
+ )
+ {
+ // NOTE TO USER :
+ // Compile error here indicates that the given type is not
+ // unambiguously convertible to one of the variant's types
+ // (or that no conversion exists).
+ //
+ indicate_which(
+ initializer::initialize(
+ storage_.address()
+ , detail::variant::move(operand)
+ )
+ );
+ }
+#endif
+
template <typename Variant>
void convert_construct(
Variant& operand
@@ -1345,6 +1539,21 @@ private: // helpers, for structors, below
);
}
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template <typename Variant>
+ typename boost::enable_if<boost::is_rvalue_reference<Variant&&> >::type convert_construct(
+ Variant&& operand
+ , long
+ , mpl::true_// is_foreign_variant
+ )
+ {
+ convert_move_into visitor(storage_.address());
+ indicate_which(
+ operand.internal_apply_visitor(visitor)
+ );
+ }
+#endif
+
template <typename Variant>
void convert_construct_variant(Variant& operand)
{
@@ -1372,6 +1581,35 @@ private: // helpers, for structors, below
);
}
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template <typename Variant>
+ typename boost::enable_if<boost::is_rvalue_reference<Variant&&> >::type convert_construct_variant(Variant&& operand)
+ {
+ // [Determine if the given variant is itself a bounded type, or if its
+ // content needs to be converted (i.e., it is a 'foreign' variant):]
+ //
+
+ typedef typename mpl::find_if<
+ types
+ , is_same<
+ add_const<mpl::_1>
+ , const Variant
+ >
+ >::type found_it;
+
+ typedef typename mpl::end<types>::type not_found;
+ typedef typename is_same<
+ found_it, not_found
+ >::type is_foreign_variant;
+
+ // Convert move construct from operand:
+ convert_construct(
+ detail::variant::move(operand), 1L
+ , is_foreign_variant()
+ );
+ }
+#endif
+
template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
void convert_construct(
boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
@@ -1390,6 +1628,17 @@ private: // helpers, for structors, below
convert_construct_variant(operand);
}
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
+ void convert_construct(
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>&& operand
+ , long
+ )
+ {
+ convert_construct_variant( detail::variant::move(operand) );
+ }
+#endif
+
public: // structors, cont.
#if !defined(BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING)
@@ -1439,8 +1688,16 @@ public: // structors, cont.
{
convert_construct(operand, 1L);
}
-
#endif // BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING workarounds
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template <class T>
+ variant(T&& operand, typename boost::enable_if<boost::is_rvalue_reference<T&&> >::type* = 0,
+ typename boost::disable_if<boost::is_const<T> >::type* = 0)
+ {
+ convert_construct( detail::variant::move(operand), 1L);
+ }
+#endif
public: // structors, cont.
@@ -1454,6 +1711,18 @@ public: // structors, cont.
// ...and activate the *this's primary storage on success:
indicate_which(operand.which());
}
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ variant(variant&& operand) BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value)
+ {
+ // Move the value of operand into *this...
+ detail::variant::move_into visitor( storage_.address() );
+ operand.internal_apply_visitor(visitor);
+
+ // ...and activate the *this's primary storage on success:
+ indicate_which(operand.which());
+ }
+#endif
private: // helpers, for modifiers (below)
@@ -1471,28 +1740,28 @@ private: // helpers, for modifiers (below)
class assigner
: public static_visitor<>
{
- private: // representation
+ protected: // representation
variant& lhs_;
- int rhs_which_;
+ const int rhs_which_;
public: // structors
- assigner(variant& lhs, int rhs_which)
+ assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT
: lhs_(lhs)
, rhs_which_(rhs_which)
{
}
- private: // helpers, for internal visitor interface (below)
+ protected: // helpers, for internal visitor interface (below)
template <typename RhsT, typename B1, typename B2>
void assign_impl(
const RhsT& rhs_content
- , mpl::true_// has_nothrow_copy
- , B1// has_nothrow_move_constructor
- , B2// has_fallback_type
- )
+ , mpl::true_ // has_nothrow_copy
+ , B1 // is_nothrow_move_constructible
+ , B2 // has_fallback_type
+ ) const BOOST_NOEXCEPT
{
// Destroy lhs's content...
lhs_.destroy_content(); // nothrow
@@ -1508,10 +1777,10 @@ private: // helpers, for modifiers (below)
template <typename RhsT, typename B>
void assign_impl(
const RhsT& rhs_content
- , mpl::false_// has_nothrow_copy
- , mpl::true_// has_nothrow_move_constructor
- , B// has_fallback_type
- )
+ , mpl::false_ // has_nothrow_copy
+ , mpl::true_ // is_nothrow_move_constructible
+ , B // has_fallback_type
+ ) const
{
// Attempt to make a temporary copy (so as to move it below)...
RhsT temp(rhs_content);
@@ -1527,37 +1796,42 @@ private: // helpers, for modifiers (below)
lhs_.indicate_which(rhs_which_); // nothrow
}
+ void construct_fallback() const BOOST_NOEXCEPT {
+ // In case of failure, default-construct fallback type in lhs's storage...
+ new (lhs_.storage_.address())
+ fallback_type_; // nothrow
+
+ // ...indicate construction of fallback type...
+ lhs_.indicate_which(
+ BOOST_MPL_AUX_VALUE_WKND(fallback_type_index_)::value
+ ); // nothrow
+ }
+
template <typename RhsT>
void assign_impl(
const RhsT& rhs_content
- , mpl::false_// has_nothrow_copy
- , mpl::false_// has_nothrow_move_constructor
- , mpl::true_// has_fallback_type
- )
+ , mpl::false_ // has_nothrow_copy
+ , mpl::false_ // is_nothrow_move_constructible
+ , mpl::true_ // has_fallback_type
+ ) const
{
// Destroy lhs's content...
lhs_.destroy_content(); // nothrow
- try
+ BOOST_TRY
{
// ...and attempt to copy rhs's content into lhs's storage:
new(lhs_.storage_.address())
RhsT( rhs_content );
}
- catch (...)
+ BOOST_CATCH (...)
{
- // In case of failure, default-construct fallback type in lhs's storage...
- new (lhs_.storage_.address())
- fallback_type_; // nothrow
-
- // ...indicate construction of fallback type...
- lhs_.indicate_which(
- BOOST_MPL_AUX_VALUE_WKND(fallback_type_index_)::value
- ); // nothrow
+ construct_fallback();
// ...and rethrow:
- throw;
+ BOOST_RETHROW;
}
+ BOOST_CATCH_END
// In the event of success, indicate new content type:
lhs_.indicate_which(rhs_which_); // nothrow
@@ -1566,10 +1840,10 @@ private: // helpers, for modifiers (below)
template <typename RhsT>
void assign_impl(
const RhsT& rhs_content
- , mpl::false_// has_nothrow_copy
- , mpl::false_// has_nothrow_move_constructor
- , mpl::false_// has_fallback_type
- )
+ , mpl::false_ // has_nothrow_copy
+ , mpl::false_ // is_nothrow_move_constructible
+ , mpl::false_ // has_fallback_type
+ ) const
{
detail::variant::backup_assigner<wknd_self_t>
visitor(lhs_, rhs_which_, rhs_content);
@@ -1580,13 +1854,13 @@ private: // helpers, for modifiers (below)
template <typename RhsT>
BOOST_VARIANT_AUX_RETURN_VOID_TYPE
- internal_visit(const RhsT& rhs_content, int)
+ internal_visit(const RhsT& rhs_content, int) const
{
typedef typename has_nothrow_copy<RhsT>::type
nothrow_copy;
typedef typename mpl::or_< // reduces compile-time
nothrow_copy
- , detail::variant::has_nothrow_move_constructor<RhsT>
+ , is_nothrow_move_constructible<RhsT>
>::type nothrow_move_constructor;
assign_impl(
@@ -1605,8 +1879,131 @@ private: // helpers, for modifiers (below)
assigner& operator= (assigner const&);
#endif
};
-
+
friend class assigner;
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ // class move_assigner
+ //
+ // Internal visitor that "move assigns" the visited value to the given variant
+ // by appropriate destruction and move-construction.
+ //
+
+ class move_assigner
+ : public assigner
+ {
+ public: // structors
+
+ move_assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT
+ : assigner(lhs, rhs_which)
+ {
+ }
+
+ private: // helpers, for internal visitor interface (below)
+
+ template <typename RhsT, typename B2>
+ void assign_impl(
+ RhsT& rhs_content
+ , mpl::true_ // has_nothrow_copy
+ , mpl::false_ // is_nothrow_move_constructible
+ , B2 // has_fallback_type
+ ) const BOOST_NOEXCEPT
+ {
+ assigner::assign_impl(rhs_content, mpl::true_(), mpl::false_(), B2());
+ }
+
+ template <typename RhsT, typename B, typename B2>
+ void assign_impl(
+ RhsT& rhs_content
+ , B // has_nothrow_copy
+ , mpl::true_ // is_nothrow_move_constructible
+ , B2 // has_fallback_type
+ ) const BOOST_NOEXCEPT
+ {
+ // ...destroy lhs's content...
+ assigner::lhs_.destroy_content(); // nothrow
+
+ // ...move the rhs_content into lhs's storage...
+ new(assigner::lhs_.storage_.address())
+ RhsT( detail::variant::move(rhs_content) ); // nothrow
+
+ // ...and indicate new content type:
+ assigner::lhs_.indicate_which(assigner::rhs_which_); // nothrow
+ }
+
+ template <typename RhsT>
+ void assign_impl(
+ RhsT& rhs_content
+ , mpl::false_ // has_nothrow_copy
+ , mpl::false_ // is_nothrow_move_constructible
+ , mpl::true_ // has_fallback_type
+ ) const
+ {
+ // Destroy lhs's content...
+ assigner::lhs_.destroy_content(); // nothrow
+
+ BOOST_TRY
+ {
+ // ...and attempt to copy rhs's content into lhs's storage:
+ new(assigner::lhs_.storage_.address())
+ RhsT( detail::variant::move(rhs_content) );
+ }
+ BOOST_CATCH (...)
+ {
+ assigner::construct_fallback();
+
+ // ...and rethrow:
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+
+ // In the event of success, indicate new content type:
+ assigner::lhs_.indicate_which(assigner::rhs_which_); // nothrow
+ }
+
+ template <typename RhsT>
+ void assign_impl(
+ RhsT& rhs_content
+ , mpl::false_ // has_nothrow_copy
+ , mpl::false_ // is_nothrow_move_constructible
+ , mpl::false_ // has_fallback_type
+ ) const
+ {
+ assigner::assign_impl(rhs_content, mpl::false_(), mpl::false_(), mpl::false_());
+ }
+
+ public: // internal visitor interfaces
+
+ template <typename RhsT>
+ BOOST_VARIANT_AUX_RETURN_VOID_TYPE
+ internal_visit(RhsT& rhs_content, int) const
+ {
+ typedef typename is_nothrow_move_constructible<RhsT>::type
+ nothrow_move_constructor;
+ typedef typename mpl::or_< // reduces compile-time
+ nothrow_move_constructor
+ , has_nothrow_copy<RhsT>
+ >::type nothrow_copy;
+
+ assign_impl(
+ rhs_content
+ , nothrow_copy()
+ , nothrow_move_constructor()
+ , has_fallback_type_()
+ );
+
+ BOOST_VARIANT_AUX_RETURN_VOID;
+ }
+
+#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
+ private:
+ // silence MSVC warning C4512: assignment operator could not be generated
+ move_assigner& operator= (move_assigner const&);
+#endif
+ };
+
+ friend class move_assigner;
+#endif // BOOST_NO_CXX11_RVALUE_REFERENCES
void variant_assign(const variant& rhs)
{
@@ -1625,6 +2022,25 @@ private: // helpers, for modifiers (below)
}
}
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ void variant_assign(variant&& rhs)
+ {
+ // If the contained types are EXACTLY the same...
+ if (which_ == rhs.which_)
+ {
+ // ...then move rhs's storage to lhs's content:
+ detail::variant::move_storage visitor(rhs.storage_.address());
+ this->internal_apply_visitor(visitor);
+ }
+ else
+ {
+ // Otherwise, perform general (move-based) variant assignment:
+ move_assigner visitor(*this, rhs.which());
+ rhs.internal_apply_visitor(visitor);
+ }
+ }
+#endif // BOOST_NO_CXX11_RVALUE_REFERENCES
+
private: // helpers, for modifiers (below)
template <typename T>
@@ -1645,8 +2061,38 @@ private: // helpers, for modifiers (below)
}
}
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template <typename T>
+ void move_assign(T&& rhs)
+ {
+ // If direct T-to-T move assignment is not possible...
+ detail::variant::direct_mover<T> direct_move(rhs);
+ if (this->apply_visitor(direct_move) == false)
+ {
+ // ...then convert rhs to variant and assign:
+ //
+ // While potentially inefficient, the following construction of a
+ // variant allows T as any type convertible to one of the bounded
+ // types without excessive code redundancy.
+ //
+ variant temp( detail::variant::move(rhs) );
+ variant_assign( detail::variant::move(temp) );
+ }
+ }
+#endif // BOOST_NO_CXX11_RVALUE_REFERENCES
+
public: // modifiers
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template <class T>
+ typename boost::enable_if_c<boost::is_rvalue_reference<T&&>::value && !boost::is_const<T>::value, variant& >::type
+ operator=(T&& rhs)
+ {
+ move_assign( detail::variant::move(rhs) );
+ return *this;
+ }
+#endif // BOOST_NO_CXX11_RVALUE_REFERENCES
+
template <typename T>
variant& operator=(const T& rhs)
{
@@ -1661,6 +2107,17 @@ public: // modifiers
return *this;
}
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ variant& operator=(variant&& rhs)
+#if !defined(__GNUC__) || (__GNUC__ != 4) || (__GNUC_MINOR__ > 6)
+ BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value && variant_move_noexcept_assignable::type::value)
+#endif
+ {
+ variant_assign( detail::variant::move(rhs) );
+ return *this;
+ }
+#endif // BOOST_NO_CXX11_RVALUE_REFERENCES
+
void swap(variant& rhs)
{
// If the contained types are the same...
@@ -1685,7 +2142,7 @@ public: // queries
// NOTE: member which() defined above.
//
- bool empty() const
+ bool empty() const BOOST_NOEXCEPT
{
return false;
}
@@ -1700,33 +2157,18 @@ public: // queries
public: // prevent comparison with foreign types
-#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
-
+// Obsolete. Remove.
# define BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE \
void
-#else // MSVC7
-
- //
- // MSVC7 gives error about return types for above being different than
- // the true comparison operator overloads:
- //
-
-# define BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE \
- bool
-
-#endif // MSVC7 workaround
-
template <typename U>
- BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE
- operator==(const U&) const
+ void operator==(const U&) const
{
BOOST_STATIC_ASSERT( false && sizeof(U) );
}
template <typename U>
- BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE
- operator<(const U&) const
+ void operator<(const U&) const
{
BOOST_STATIC_ASSERT( false && sizeof(U) );
}
@@ -1859,9 +2301,7 @@ struct make_variant_over
{
private: // precondition assertions
-#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
BOOST_STATIC_ASSERT(( ::boost::mpl::is_sequence<Types>::value ));
-#endif
public: // metafunction result