Boost logo

Boost-Commit :

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


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