|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r81793 - in branches/release: boost/variant boost/variant/detail libs/variant/test
From: antoshkka_at_[hidden]
Date: 2012-12-08 10:44:17
Author: apolukhin
Date: 2012-12-08 10:44:16 EST (Sat, 08 Dec 2012)
New Revision: 81793
URL: http://svn.boost.org/trac/boost/changeset/81793
Log:
Merge variant from trunk:
* Fix #7718 (move constructor from template type added)
* More tests and minor bugfixes
* Deprecated macros replaced with new ones (thanks to Marshall Clow)
Text files modified:
branches/release/boost/variant/detail/initializer.hpp | 27 ++++++
branches/release/boost/variant/detail/move.hpp | 2
branches/release/boost/variant/recursive_wrapper.hpp | 39 ++++++++
branches/release/boost/variant/variant.hpp | 180 ++++++++++++++++++++++++++++++++++++---
branches/release/libs/variant/test/rvalue_test.cpp | 56 ++++++++++++
5 files changed, 285 insertions(+), 19 deletions(-)
Modified: branches/release/boost/variant/detail/initializer.hpp
==============================================================================
--- branches/release/boost/variant/detail/initializer.hpp (original)
+++ branches/release/boost/variant/detail/initializer.hpp 2012-12-08 10:44:16 EST (Sat, 08 Dec 2012)
@@ -20,6 +20,7 @@
#include "boost/call_traits.hpp"
#include "boost/detail/reference_content.hpp"
#include "boost/variant/recursive_wrapper_fwd.hpp"
+#include "boost/variant/detail/move.hpp"
#if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
# include "boost/mpl/aux_/value_wknd.hpp"
@@ -79,8 +80,22 @@
recursive_enabled_T;
typedef typename unwrap_recursive<recursive_enabled_T>::type
public_T;
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ typedef boost::is_reference<public_T>
+ is_reference_content_t;
+
+ typedef typename boost::mpl::if_<is_reference_content_t, public_T, const public_T& >::type
+ param_T;
+
+ template <class T> struct disable_overload{};
+
+ typedef typename boost::mpl::if_<is_reference_content_t, disable_overload<public_T>, public_T&& >::type
+ param2_T;
+#else
typedef typename call_traits<public_T>::param_type
param_T;
+#endif
public: // static functions
@@ -96,6 +111,18 @@
return BOOST_MPL_AUX_VALUE_WKND(index)::value; // which
}
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ static int initialize(void* dest, param2_T operand)
+ {
+ // This assert must newer trigger, because all the reference contents are
+ // handled by the initilize(void* dest, param_T operand) function above
+ BOOST_ASSERT(!is_reference_content_t::value);
+
+ typedef typename boost::mpl::if_<is_reference_content_t, param2_T, recursive_enabled_T>::type value_T;
+ new(dest) value_T( boost::detail::variant::move(operand) );
+ return BOOST_MPL_AUX_VALUE_WKND(index)::value; // which
+ }
+#endif
};
friend class initializer_node;
Modified: branches/release/boost/variant/detail/move.hpp
==============================================================================
--- branches/release/boost/variant/detail/move.hpp (original)
+++ branches/release/boost/variant/detail/move.hpp 2012-12-08 10:44:16 EST (Sat, 08 Dec 2012)
@@ -82,7 +82,7 @@
} // namespace detail
-#ifdef BOOST_NO_RVALUE_REFERENCES
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
template <typename T>
inline
Modified: branches/release/boost/variant/recursive_wrapper.hpp
==============================================================================
--- branches/release/boost/variant/recursive_wrapper.hpp (original)
+++ branches/release/boost/variant/recursive_wrapper.hpp 2012-12-08 10:44:16 EST (Sat, 08 Dec 2012)
@@ -14,6 +14,7 @@
#define BOOST_VARIANT_RECURSIVE_WRAPPER_HPP
#include "boost/variant/recursive_wrapper_fwd.hpp"
+#include "boost/variant/detail/move.hpp"
#include "boost/checked_delete.hpp"
namespace boost {
@@ -43,6 +44,11 @@
recursive_wrapper(const recursive_wrapper& operand);
recursive_wrapper(const T& operand);
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ recursive_wrapper(recursive_wrapper&& operand);
+ recursive_wrapper(T&& operand);
+#endif
+
private: // helpers, for modifiers (below)
void assign(const T& rhs);
@@ -61,13 +67,28 @@
return *this;
}
- void swap(recursive_wrapper& operand)
+ void swap(recursive_wrapper& operand) BOOST_NOEXCEPT
{
T* temp = operand.p_;
operand.p_ = p_;
p_ = temp;
}
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ recursive_wrapper& operator=(recursive_wrapper&& rhs) BOOST_NOEXCEPT
+ {
+ swap(rhs);
+ return *this;
+ }
+
+ recursive_wrapper& operator=(T&& rhs)
+ {
+ get() = detail::variant::move(rhs);
+ return *this;
+ }
+#endif
+
public: // queries
T& get() { return *get_pointer(); }
@@ -102,6 +123,20 @@
{
}
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+template <typename T>
+recursive_wrapper<T>::recursive_wrapper(recursive_wrapper&& operand)
+ : p_(new T( detail::variant::move(operand.get()) ))
+{
+}
+
+template <typename T>
+recursive_wrapper<T>::recursive_wrapper(T&& operand)
+ : p_(new T( detail::variant::move(operand) ))
+{
+}
+#endif
+
template <typename T>
void recursive_wrapper<T>::assign(const T& rhs)
{
@@ -113,7 +148,7 @@
// Swaps two recursive_wrapper<T> objects of the same type T.
//
template <typename T>
-inline void swap(recursive_wrapper<T>& lhs, recursive_wrapper<T>& rhs)
+inline void swap(recursive_wrapper<T>& lhs, recursive_wrapper<T>& rhs) BOOST_NOEXCEPT
{
lhs.swap(rhs);
}
Modified: branches/release/boost/variant/variant.hpp
==============================================================================
--- branches/release/boost/variant/variant.hpp (original)
+++ branches/release/boost/variant/variant.hpp 2012-12-08 10:44:16 EST (Sat, 08 Dec 2012)
@@ -437,7 +437,7 @@
//
// Internal visitor that moves the value it visits into the given buffer.
//
-#ifndef BOOST_NO_RVALUE_REFERENCES
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
class move_into
: public static_visitor<>
{
@@ -1380,7 +1380,7 @@
destroy_content();
}
- variant() BOOST_NOEXCEPT_IF(boost::has_nothrow_constructor<internal_T0>::type::value)
+ variant()
{
// NOTE TO USER :
// Compile error from here indicates that the first bound
@@ -1468,6 +1468,74 @@
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>
@@ -1490,6 +1558,28 @@
);
}
+#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
@@ -1503,6 +1593,21 @@
);
}
+#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)
{
@@ -1530,6 +1635,35 @@
);
}
+#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
@@ -1548,6 +1682,17 @@
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)
@@ -1597,8 +1742,15 @@
{
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)
+ {
+ convert_construct( detail::variant::move(operand), 1L);
+ }
+#endif
public: // structors, cont.
@@ -1613,7 +1765,7 @@
indicate_which(operand.which());
}
-#ifndef BOOST_NO_RVALUE_REFERENCES
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
variant(variant&& operand)
{
// Move the value of operand into *this...
@@ -1778,7 +1930,7 @@
friend class assigner;
-#ifndef BOOST_NO_RVALUE_REFERENCES
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// class move_assigner
//
// Internal visitor that "move assigns" the visited value to the given variant
@@ -1921,7 +2073,7 @@
};
friend class move_assigner;
-#endif // BOOST_NO_RVALUE_REFERENCES
+#endif // BOOST_NO_CXX11_RVALUE_REFERENCES
void variant_assign(const variant& rhs)
{
@@ -1940,7 +2092,7 @@
}
}
-#ifndef BOOST_NO_RVALUE_REFERENCES
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
void variant_assign(variant&& rhs)
{
// If the contained types are EXACTLY the same...
@@ -1957,7 +2109,7 @@
rhs.internal_apply_visitor(visitor);
}
}
-#endif // BOOST_NO_RVALUE_REFERENCES
+#endif // BOOST_NO_CXX11_RVALUE_REFERENCES
private: // helpers, for modifiers (below)
@@ -1979,7 +2131,7 @@
}
}
-#ifndef BOOST_NO_RVALUE_REFERENCES
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <typename T>
void move_assign(T&& rhs)
{
@@ -1997,18 +2149,18 @@
variant_assign( detail::variant::move(temp) );
}
}
-#endif // BOOST_NO_RVALUE_REFERENCES
+#endif // BOOST_NO_CXX11_RVALUE_REFERENCES
public: // modifiers
-#ifndef BOOST_NO_RVALUE_REFERENCES
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <class T>
typename boost::enable_if<boost::is_rvalue_reference<T&&>, variant& >::type operator=(T&& rhs)
{
move_assign( detail::variant::move(rhs) );
return *this;
}
-#endif // BOOST_NO_RVALUE_REFERENCES
+#endif // BOOST_NO_CXX11_RVALUE_REFERENCES
template <typename T>
variant& operator=(const T& rhs)
@@ -2024,13 +2176,13 @@
return *this;
}
-#ifndef BOOST_NO_RVALUE_REFERENCES
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
variant& operator=(variant&& rhs)
{
variant_assign( detail::variant::move(rhs) );
return *this;
}
-#endif // BOOST_NO_RVALUE_REFERENCES
+#endif // BOOST_NO_CXX11_RVALUE_REFERENCES
void swap(variant& rhs)
{
Modified: branches/release/libs/variant/test/rvalue_test.cpp
==============================================================================
--- branches/release/libs/variant/test/rvalue_test.cpp (original)
+++ branches/release/libs/variant/test/rvalue_test.cpp 2012-12-08 10:44:16 EST (Sat, 08 Dec 2012)
@@ -15,15 +15,25 @@
#include "boost/test/minimal.hpp"
#include "boost/variant.hpp"
-// This test requires BOOST_HAS_RVALUE_REFS
+// This test requires rvalue references support
-#ifndef BOOST_HAS_RVALUE_REFS
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
void run()
{
BOOST_CHECK(true);
}
+void run1()
+{
+ BOOST_CHECK(true);
+}
+
+void run_move_only()
+{
+ BOOST_CHECK(true);
+}
+
#else
class move_copy_conting_class {
@@ -126,6 +136,46 @@
BOOST_CHECK(total_count <= move_copy_conting_class::moves_count + move_copy_conting_class::copy_count);
}
+void run1()
+{
+ move_copy_conting_class::moves_count = 0;
+ move_copy_conting_class::copy_count = 0;
+
+ move_copy_conting_class c1;
+ typedef boost::variant<int, move_copy_conting_class> variant_I_type;
+ variant_I_type v1(static_cast<move_copy_conting_class&&>(c1));
+
+ // Assuring that `move_copy_conting_class` was not copyied
+ BOOST_CHECK(move_copy_conting_class::copy_count == 0);
+ BOOST_CHECK(move_copy_conting_class::moves_count > 0);
+}
+
+struct move_only_structure {
+ move_only_structure(){}
+ move_only_structure(move_only_structure&&){}
+ move_only_structure& operator=(move_only_structure&&) { return *this; }
+
+private:
+ move_only_structure(const move_only_structure&);
+ move_only_structure& operator=(const move_only_structure&);
+};
+
+void run_move_only()
+{
+ move_only_structure mo;
+ boost::variant<int, move_only_structure > vi, vi2(static_cast<move_only_structure&&>(mo));
+ BOOST_CHECK(vi.which() == 0);
+ BOOST_CHECK(vi2.which() == 1);
+
+ vi = 10;
+ vi2 = 10;
+ BOOST_CHECK(vi.which() == 0);
+ BOOST_CHECK(vi2.which() == 0);
+
+ vi = static_cast<move_only_structure&&>(mo);
+ vi2 = static_cast<move_only_structure&&>(mo);
+ BOOST_CHECK(vi.which() == 1);
+}
#endif
@@ -133,5 +183,7 @@
int test_main(int , char* [])
{
run();
+ run1();
+ run_move_only();
return 0;
}
\ No newline at end of file
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk