Boost logo

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