Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r81455 - in branches/release: boost/variant boost/variant/detail libs/variant libs/variant/test
From: antoshkka_at_[hidden]
Date: 2012-11-21 09:47:13


Author: apolukhin
Date: 2012-11-21 09:47:12 EST (Wed, 21 Nov 2012)
New Revision: 81455
URL: http://svn.boost.org/trac/boost/changeset/81455

Log:
Merge from trunk: added basic rvalue support and marked some functions with BOOST_NOEXCEPT (fixes #7620)
Added:
   branches/release/libs/variant/test/rvalue_test.cpp (contents, props changed)
Properties modified:
   branches/release/libs/variant/ (props changed)
Text files modified:
   branches/release/boost/variant/detail/backup_holder.hpp | 7
   branches/release/boost/variant/detail/move.hpp | 8
   branches/release/boost/variant/variant.hpp | 405 ++++++++++++++++++++++++++++++++++++++-
   branches/release/libs/variant/test/Jamfile.v2 | 1
   4 files changed, 401 insertions(+), 20 deletions(-)

Modified: branches/release/boost/variant/detail/backup_holder.hpp
==============================================================================
--- branches/release/boost/variant/detail/backup_holder.hpp (original)
+++ branches/release/boost/variant/detail/backup_holder.hpp 2012-11-21 09:47:12 EST (Wed, 21 Nov 2012)
@@ -13,6 +13,7 @@
 #ifndef BOOST_VARIANT_DETAIL_BACKUP_HOLDER_HPP
 #define BOOST_VARIANT_DETAIL_BACKUP_HOLDER_HPP
 
+#include "boost/config.hpp"
 #include "boost/assert.hpp"
 
 namespace boost {
@@ -32,7 +33,7 @@
         delete backup_;
     }
 
- explicit backup_holder(T* backup)
+ explicit backup_holder(T* backup) BOOST_NOEXCEPT
         : backup_(backup)
     {
     }
@@ -53,7 +54,7 @@
         return *this;
     }
 
- void swap(backup_holder& rhs)
+ void swap(backup_holder& rhs) BOOST_NOEXCEPT
     {
         T* tmp = rhs.backup_;
         rhs.backup_ = this->backup_;
@@ -83,7 +84,7 @@
 }
 
 template <typename T>
-void swap(backup_holder<T>& lhs, backup_holder<T>& rhs)
+void swap(backup_holder<T>& lhs, backup_holder<T>& rhs) BOOST_NOEXCEPT
 {
     lhs.swap(rhs);
 }

Modified: branches/release/boost/variant/detail/move.hpp
==============================================================================
--- branches/release/boost/variant/detail/move.hpp (original)
+++ branches/release/boost/variant/detail/move.hpp 2012-11-21 09:47:12 EST (Wed, 21 Nov 2012)
@@ -82,6 +82,8 @@
 
 } // namespace detail
 
+#ifdef BOOST_NO_RVALUE_REFERENCES
+
 template <typename T>
 inline
     typename detail::move_type<T>::type
@@ -93,6 +95,12 @@
     return move_t(source);
 }
 
+#else
+
+using std::move;
+
+#endif
+
 //////////////////////////////////////////////////////////////////////////
 // class template return_t
 //

Modified: branches/release/boost/variant/variant.hpp
==============================================================================
--- branches/release/boost/variant/variant.hpp (original)
+++ branches/release/boost/variant/variant.hpp 2012-11-21 09:47:12 EST (Wed, 21 Nov 2012)
@@ -51,7 +51,9 @@
 #include "boost/type_traits/has_nothrow_copy.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"
 
@@ -338,7 +340,7 @@
 
 public: // visitor interface
 
- T& operator()(T& operand) const
+ T& operator()(T& operand) const BOOST_NOEXCEPT
     {
         return operand;
     }
@@ -397,7 +399,7 @@
 
 public: // structors
 
- explicit copy_into(void* storage)
+ explicit copy_into(void* storage) BOOST_NOEXCEPT
         : storage_(storage)
     {
     }
@@ -431,6 +433,46 @@
 };
 
 ///////////////////////////////////////////////////////////////////////////////
+// (detail) class move_into
+//
+// Internal visitor that moves the value it visits into the given buffer.
+//
+#ifndef BOOST_NO_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 +487,7 @@
 
 public: // structors
 
- explicit assign_storage(const void* rhs_storage)
+ explicit assign_storage(const void* rhs_storage) BOOST_NOEXCEPT
         : rhs_storage_(rhs_storage)
     {
     }
@@ -488,6 +530,63 @@
 };
 
 ///////////////////////////////////////////////////////////////////////////////
+// (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,7 +603,7 @@
 
 public: // structors
 
- explicit direct_assigner(const T& rhs)
+ explicit direct_assigner(const T& rhs) BOOST_NOEXCEPT
         : rhs_(rhs)
     {
     }
@@ -520,7 +619,7 @@
     }
 
     template <typename U>
- bool operator()(U&)
+ bool operator()(U&) BOOST_NOEXCEPT
     {
         return false;
     }
@@ -560,6 +659,65 @@
 };
 
 ///////////////////////////////////////////////////////////////////////////////
+// (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
+
+ T& rhs_;
+
+public: // structors
+
+ explicit direct_mover(T& rhs) BOOST_NOEXCEPT
+ : rhs_(rhs)
+ {
+ }
+
+#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+
+public: // visitor interface
+
+ bool operator()(T& lhs)
+ {
+ lhs = ::boost::detail::variant::move(rhs_);
+ return true;
+ }
+
+ template <typename U>
+ bool operator()(U&) BOOST_NOEXCEPT
+ {
+ return false;
+ }
+
+#else // MSVC6
+
+public: // visitor interface
+
+ template <typename U>
+ bool operator()(U& lhs)
+ {
+ // MSVC6 can not use direct_mover class
+ return direct_assigner(rhs_)(lhs);
+ }
+
+#endif // MSVC6 workaround
+
+#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
+private:
+ // silence MSVC warning C4512: assignment operator could not be generated
+ direct_mover& operator= (direct_mover const&);
+#endif
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
 // (detail) class backup_assigner
 //
 // Internal visitor that "assigns" the given value to the visited value,
@@ -745,7 +903,7 @@
 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 +930,7 @@
 
 public: // structors
 
- explicit comparer(const Variant& lhs)
+ explicit comparer(const Variant& lhs) BOOST_NOEXCEPT
         : lhs_(lhs)
     {
     }
@@ -844,7 +1002,7 @@
 
 public: // structors
 
- explicit invoke_visitor(Visitor& visitor)
+ explicit invoke_visitor(Visitor& visitor) BOOST_NOEXCEPT
         : visitor_(visitor)
     {
     }
@@ -1170,26 +1328,26 @@
     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())
@@ -1222,7 +1380,7 @@
         destroy_content();
     }
 
- variant()
+ variant() BOOST_NOEXCEPT_IF(boost::has_nothrow_constructor<internal_T0>::type::value)
     {
         // NOTE TO USER :
         // Compile error from here indicates that the first bound
@@ -1244,7 +1402,7 @@
 
     public: // structors
 
- explicit convert_copy_into(void* storage)
+ explicit convert_copy_into(void* storage) BOOST_NOEXCEPT
             : storage_(storage)
         {
         }
@@ -1454,6 +1612,18 @@
         // ...and activate the *this's primary storage on success:
         indicate_which(operand.which());
     }
+
+#ifndef BOOST_NO_RVALUE_REFERENCES
+ variant(variant&& operand)
+ {
+ // 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)
 
@@ -1478,7 +1648,7 @@
 
     public: // structors
 
- assigner(variant& lhs, int rhs_which)
+ assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT
             : lhs_(lhs)
             , rhs_which_(rhs_which)
         {
@@ -1605,8 +1775,153 @@
         assigner& operator= (assigner const&);
 #endif
     };
-
+
     friend class assigner;
+
+#ifndef BOOST_NO_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 static_visitor<>
+ {
+ private: // representation
+
+ variant& lhs_;
+ int rhs_which_;
+
+ public: // structors
+
+ move_assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT
+ : lhs_(lhs)
+ , rhs_which_(rhs_which)
+ {
+ }
+
+ private: // helpers, for internal visitor interface (below)
+
+ template <typename RhsT, typename B1, typename B2>
+ void assign_impl(
+ RhsT& rhs_content
+ , mpl::true_// has_nothrow_copy
+ , mpl::false_// has_nothrow_move_constructor
+ , B2// has_fallback_type
+ )
+ {
+ // Destroy lhs's content...
+ lhs_.destroy_content(); // nothrow
+
+ // ...copy rhs content into lhs's storage...
+ new(lhs_.storage_.address())
+ RhsT( rhs_content ); // nothrow
+
+ // ...and indicate new content type:
+ lhs_.indicate_which(rhs_which_); // nothrow
+ }
+
+ template <typename RhsT, typename B>
+ void assign_impl(
+ RhsT& rhs_content
+ , mpl::true_// has_nothrow_copy
+ , mpl::true_// has_nothrow_move_constructor
+ , B// has_fallback_type
+ )
+ {
+ // ...destroy lhs's content...
+ lhs_.destroy_content(); // nothrow
+
+ // ...move the rhs_content into lhs's storage...
+ new(lhs_.storage_.address())
+ RhsT( detail::variant::move(rhs_content) ); // nothrow
+
+ // ...and indicate new content type:
+ lhs_.indicate_which(rhs_which_); // nothrow
+ }
+
+ template <typename RhsT>
+ void assign_impl(
+ RhsT& rhs_content
+ , mpl::false_// has_nothrow_copy
+ , mpl::false_// has_nothrow_move_constructor
+ , mpl::true_// has_fallback_type
+ )
+ {
+ // Destroy lhs's content...
+ lhs_.destroy_content(); // nothrow
+
+ try
+ {
+ // ...and attempt to copy rhs's content into lhs's storage:
+ new(lhs_.storage_.address())
+ RhsT( detail::variant::move(rhs_content) );
+ }
+ 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
+
+ // ...and rethrow:
+ throw;
+ }
+
+ // In the event of success, indicate new content type:
+ lhs_.indicate_which(rhs_which_); // nothrow
+ }
+
+ 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
+ )
+ {
+ detail::variant::backup_assigner<wknd_self_t>
+ visitor(lhs_, rhs_which_, rhs_content);
+ lhs_.internal_apply_visitor(visitor);
+ }
+
+ public: // internal visitor interfaces
+
+ template <typename RhsT>
+ BOOST_VARIANT_AUX_RETURN_VOID_TYPE
+ internal_visit(RhsT& rhs_content, int)
+ {
+ typedef typename detail::variant::has_nothrow_move_constructor<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_RVALUE_REFERENCES
 
     void variant_assign(const variant& rhs)
     {
@@ -1625,6 +1940,25 @@
         }
     }
 
+#ifndef BOOST_NO_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_RVALUE_REFERENCES
+
 private: // helpers, for modifiers (below)
 
     template <typename T>
@@ -1645,8 +1979,37 @@
         }
     }
 
+#ifndef BOOST_NO_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_RVALUE_REFERENCES
+
 public: // modifiers
 
+#ifndef BOOST_NO_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
+
     template <typename T>
     variant& operator=(const T& rhs)
     {
@@ -1661,6 +2024,14 @@
         return *this;
     }
 
+#ifndef BOOST_NO_RVALUE_REFERENCES
+ variant& operator=(variant&& rhs)
+ {
+ variant_assign( detail::variant::move(rhs) );
+ return *this;
+ }
+#endif // BOOST_NO_RVALUE_REFERENCES
+
     void swap(variant& rhs)
     {
         // If the contained types are the same...
@@ -1685,7 +2056,7 @@
     // NOTE: member which() defined above.
     //
 
- bool empty() const
+ bool empty() const BOOST_NOEXCEPT
     {
         return false;
     }

Modified: branches/release/libs/variant/test/Jamfile.v2
==============================================================================
--- branches/release/libs/variant/test/Jamfile.v2 (original)
+++ branches/release/libs/variant/test/Jamfile.v2 2012-11-21 09:47:12 EST (Wed, 21 Nov 2012)
@@ -33,6 +33,7 @@
     [ run variant_comparison_test.cpp ]
     [ run variant_visit_test.cpp ]
     [ run hash_variant_test.cpp ]
+ [ run rvalue_test.cpp ]
    ;
 
 

Added: branches/release/libs/variant/test/rvalue_test.cpp
==============================================================================
--- (empty file)
+++ branches/release/libs/variant/test/rvalue_test.cpp 2012-11-21 09:47:12 EST (Wed, 21 Nov 2012)
@@ -0,0 +1,137 @@
+//-----------------------------------------------------------------------------
+// boost-libs variant/test/rvalue_test.cpp source file
+// See http://www.boost.org for updates, documentation, and revision history.
+//-----------------------------------------------------------------------------
+//
+// Copyright (c) 2012
+// 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)
+
+#include "boost/config.hpp"
+
+#include "boost/test/minimal.hpp"
+#include "boost/variant.hpp"
+
+// This test requires BOOST_HAS_RVALUE_REFS
+
+#ifndef BOOST_HAS_RVALUE_REFS
+
+void run()
+{
+ BOOST_CHECK(true);
+}
+
+#else
+
+class move_copy_conting_class {
+public:
+ static unsigned int moves_count;
+ static unsigned int copy_count;
+
+ move_copy_conting_class(){}
+ move_copy_conting_class(move_copy_conting_class&&) {
+ ++ moves_count;
+ }
+
+ move_copy_conting_class& operator=(move_copy_conting_class&&) {
+ ++ moves_count;
+ return *this;
+ }
+
+ move_copy_conting_class(const move_copy_conting_class&) {
+ ++ copy_count;
+ }
+ move_copy_conting_class& operator=(const move_copy_conting_class&) {
+ ++ copy_count;
+ return *this;
+ }
+};
+
+unsigned int move_copy_conting_class::moves_count = 0;
+unsigned int move_copy_conting_class::copy_count = 0;
+
+void run()
+{
+ typedef boost::variant<int, move_copy_conting_class> variant_I_type;
+ variant_I_type v1, v2;
+
+ // Assuring that `move_copy_conting_class` was not created
+ BOOST_CHECK(move_copy_conting_class::copy_count == 0);
+ BOOST_CHECK(move_copy_conting_class::moves_count == 0);
+
+ v1 = move_copy_conting_class();
+ // Assuring that `move_copy_conting_class` was moved at least once
+ BOOST_CHECK(move_copy_conting_class::moves_count != 0);
+
+ unsigned int total_count = move_copy_conting_class::moves_count + move_copy_conting_class::copy_count;
+ move_copy_conting_class var;
+ v1 = 0;
+ move_copy_conting_class::moves_count = 0;
+ move_copy_conting_class::copy_count = 0;
+ v1 = var;
+ // Assuring that move assignment operator moves/copyes value not more times than copy assignment operator
+ BOOST_CHECK(total_count <= move_copy_conting_class::moves_count + move_copy_conting_class::copy_count);
+
+ move_copy_conting_class::moves_count = 0;
+ move_copy_conting_class::copy_count = 0;
+ v2 = static_cast<variant_I_type&&>(v1);
+ // Assuring that `move_copy_conting_class` in v1 was moved at least once and was not copied
+ BOOST_CHECK(move_copy_conting_class::moves_count != 0);
+ BOOST_CHECK(move_copy_conting_class::copy_count == 0);
+
+ v1 = move_copy_conting_class();
+ move_copy_conting_class::moves_count = 0;
+ move_copy_conting_class::copy_count = 0;
+ v2 = static_cast<variant_I_type&&>(v1);
+ // Assuring that `move_copy_conting_class` in v1 was moved at least once and was not copied
+ BOOST_CHECK(move_copy_conting_class::moves_count != 0);
+ BOOST_CHECK(move_copy_conting_class::copy_count == 0);
+ total_count = move_copy_conting_class::moves_count + move_copy_conting_class::copy_count;
+ move_copy_conting_class::moves_count = 0;
+ move_copy_conting_class::copy_count = 0;
+ v1 = v2;
+ // Assuring that move assignment operator moves/copyes value not more times than copy assignment operator
+ BOOST_CHECK(total_count <= move_copy_conting_class::moves_count + move_copy_conting_class::copy_count);
+
+
+ typedef boost::variant<move_copy_conting_class, int> variant_II_type;
+ variant_II_type v3;
+ move_copy_conting_class::moves_count = 0;
+ move_copy_conting_class::copy_count = 0;
+ v1 = static_cast<variant_II_type&&>(v3);
+ // Assuring that `move_copy_conting_class` in v3 was moved at least once (v1 and v3 have different types)
+ BOOST_CHECK(move_copy_conting_class::moves_count != 0);
+
+ move_copy_conting_class::moves_count = 0;
+ move_copy_conting_class::copy_count = 0;
+ v2 = static_cast<variant_I_type&&>(v1);
+ // Assuring that `move_copy_conting_class` in v1 was moved at least once (v1 and v3 have different types)
+ BOOST_CHECK(move_copy_conting_class::moves_count != 0);
+
+ move_copy_conting_class::moves_count = 0;
+ move_copy_conting_class::copy_count = 0;
+ variant_I_type v5(static_cast<variant_I_type&&>(v1));
+ // Assuring that `move_copy_conting_class` in v1 was moved at least once and was not copied
+ BOOST_CHECK(move_copy_conting_class::moves_count != 0);
+ BOOST_CHECK(move_copy_conting_class::copy_count == 0);
+
+ total_count = move_copy_conting_class::moves_count + move_copy_conting_class::copy_count;
+ move_copy_conting_class::moves_count = 0;
+ move_copy_conting_class::copy_count = 0;
+ variant_I_type v6(v1);
+ // Assuring that move constructor moves/copyes value not more times than copy constructor
+ BOOST_CHECK(total_count <= move_copy_conting_class::moves_count + move_copy_conting_class::copy_count);
+}
+
+
+#endif
+
+
+int test_main(int , char* [])
+{
+ run();
+ 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