$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r81617 - in trunk: boost/variant boost/variant/detail libs/variant/test
From: antoshkka_at_[hidden]
Date: 2012-11-28 14:20:20
Author: apolukhin
Date: 2012-11-28 14:20:19 EST (Wed, 28 Nov 2012)
New Revision: 81617
URL: http://svn.boost.org/trac/boost/changeset/81617
Log:
Basic rvalues and C++11 support part 2 (refs #7718 , all bugs from patch were fixed)
Text files modified: 
   trunk/boost/variant/detail/backup_holder.hpp |     7 -                                       
   trunk/boost/variant/detail/initializer.hpp   |    27 +++++++                                 
   trunk/boost/variant/variant.hpp              |   154 +++++++++++++++++++++++++++++++++++++++ 
   trunk/libs/variant/test/rvalue_test.cpp      |    56 ++++++++++++++                          
   4 files changed, 237 insertions(+), 7 deletions(-)
Modified: trunk/boost/variant/detail/backup_holder.hpp
==============================================================================
--- trunk/boost/variant/detail/backup_holder.hpp	(original)
+++ trunk/boost/variant/detail/backup_holder.hpp	2012-11-28 14:20:19 EST (Wed, 28 Nov 2012)
@@ -13,7 +13,6 @@
 #ifndef BOOST_VARIANT_DETAIL_BACKUP_HOLDER_HPP
 #define BOOST_VARIANT_DETAIL_BACKUP_HOLDER_HPP
 
-#include "boost/config.hpp"
 #include "boost/assert.hpp"
 
 namespace boost {
@@ -33,7 +32,7 @@
         delete backup_;
     }
 
-    explicit backup_holder(T* backup) BOOST_NOEXCEPT
+    explicit backup_holder(T* backup)
         : backup_(backup)
     {
     }
@@ -54,7 +53,7 @@
         return *this;
     }
 
-    void swap(backup_holder& rhs) BOOST_NOEXCEPT
+    void swap(backup_holder& rhs)
     {
         T* tmp = rhs.backup_;
         rhs.backup_ = this->backup_;
@@ -84,7 +83,7 @@
 }
 
 template <typename T>
-void swap(backup_holder<T>& lhs, backup_holder<T>& rhs) BOOST_NOEXCEPT
+void swap(backup_holder<T>& lhs, backup_holder<T>& rhs)
 {
     lhs.swap(rhs);
 }
Modified: trunk/boost/variant/detail/initializer.hpp
==============================================================================
--- trunk/boost/variant/detail/initializer.hpp	(original)
+++ trunk/boost/variant/detail/initializer.hpp	2012-11-28 14:20:19 EST (Wed, 28 Nov 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_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_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: trunk/boost/variant/variant.hpp
==============================================================================
--- trunk/boost/variant/variant.hpp	(original)
+++ trunk/boost/variant/variant.hpp	2012-11-28 14:20:19 EST (Wed, 28 Nov 2012)
@@ -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.
 
Modified: trunk/libs/variant/test/rvalue_test.cpp
==============================================================================
--- trunk/libs/variant/test/rvalue_test.cpp	(original)
+++ trunk/libs/variant/test/rvalue_test.cpp	2012-11-28 14:20:19 EST (Wed, 28 Nov 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