Boost logo

Boost-Commit :

From: daniel_james_at_[hidden]
Date: 2008-07-13 15:26:37


Author: danieljames
Date: 2008-07-13 15:26:36 EDT (Sun, 13 Jul 2008)
New Revision: 47397
URL: http://svn.boost.org/trac/boost/changeset/47397

Log:
Implement moving swappable types.

I had to rejig the terminology a little - so 'boost_movable' means movable using
boost::move_from, 'movable' means movable by any means.

Text files modified:
   sandbox/move/boost/move.hpp | 85 +++++++++++++++++++++++++++++++++++----
   sandbox/move/libs/move/test/Jamfile.v2 | 1
   sandbox/move/libs/move/test/main.cpp | 4
   sandbox/move/libs/move/test/move.cpp | 2
   sandbox/move/libs/move/test/noncopyable.cpp | 5 --
   5 files changed, 79 insertions(+), 18 deletions(-)

Modified: sandbox/move/boost/move.hpp
==============================================================================
--- sandbox/move/boost/move.hpp (original)
+++ sandbox/move/boost/move.hpp 2008-07-13 15:26:36 EDT (Sun, 13 Jul 2008)
@@ -29,6 +29,7 @@
 #include <boost/type_traits/is_class.hpp>
 #include <boost/utility/enable_if.hpp>
 #include <boost/move/detail/config.hpp>
+#include <boost/move/detail/has_swap_overload.hpp>
 
 /*************************************************************************************************/
 
@@ -107,16 +108,42 @@
 
 /*************************************************************************************************/
 
+/*!
+\ingroup move_related
+\brief swap_from is used for move_ctors.
+*/
+
+template <typename T>
+struct swap_from
+{
+ swap_from(T& x)
+ : m(x)
+ {}
+
+ operator T() const
+ {
+ T x;
+ using std::swap;
+ swap(this->m, x);
+ return x;
+ }
+
+ T& m;
+};
+
+
+/*************************************************************************************************/
+
 #if !defined(BOOST_MOVE_NO_HAS_MOVE_ASSIGN)
 
 /*************************************************************************************************/
 
 /*!
 \ingroup move_related
-\brief The is_movable trait can be used to identify movable types.
+\brief The is_boost_movable trait can be used to identify types that are movable using this library.
 */
 template <typename T>
-struct is_movable : boost::mpl::and_<
+struct is_boost_movable : boost::mpl::and_<
                         boost::mpl::or_<
                             boost::is_convertible<T, move_from<T> >,
                             boost::is_convertible<move_from<T>, T>
@@ -133,7 +160,7 @@
 // unless the trait is specialized.
 
 template <typename T>
-struct is_movable : boost::mpl::false_ { };
+struct is_boost_movable : boost::mpl::false_ { };
 
 #endif
 
@@ -145,16 +172,32 @@
 
 struct copy_tag {};
 struct move_tag {};
+struct swap_tag {};
 
 template <typename T, class Enable = void>
-struct move_type {
- typedef copy_tag type;
-};
+struct move_type :
+ boost::mpl::if_<is_boost_movable<T>, move_tag,
+ typename boost::mpl::if_<boost::detail::has_swap_overload<T>,
+ swap_tag, copy_tag>::type > {};
+
+/*************************************************************************************************/
+
+#endif
+
+/*************************************************************************************************/
 
+/*!
+\ingroup move_related
+\brief The is_movable trait can be used to identify movable types.
+*/
 template <typename T>
-struct move_type<T, typename boost::enable_if<is_movable<T> >::type> {
- typedef move_tag type;
-};
+struct is_movable : boost::mpl::not_<boost::is_same<
+ typename boost::move_type<T>::type, copy_tag > > {};
+
+
+/*************************************************************************************************/
+
+#if !defined(BOOST_NO_SFINAE)
 
 /*************************************************************************************************/
 
@@ -241,6 +284,15 @@
 
 /*************************************************************************************************/
 
+/*!
+\ingroup move_related
+\brief This version of move is selected when T is swappable.
+*/
+template <typename T>
+T move(T& x, typename move_type_sink<swap_tag, T>::type = 0) { return T(swap_from<T>(x)); }
+
+/*************************************************************************************************/
+
 #else // BOOST_NO_SFINAE
 
 // On compilers without SFINAE, define copy_sink to always use the copy function.
@@ -377,7 +429,6 @@
 
 /*************************************************************************************************/
 
-
 /*!
 \ingroup move_related
 \brief Placement copy construction, selected when T is_movable is false
@@ -392,6 +443,20 @@
 
 /*!
 \ingroup move_related
+\brief Placement copy construction, selected when T is swappable.
+*/
+template <typename T> // T models Regular
+inline void move_construct(T* p, T& x, typename move_type_sink<swap_tag, T>::type = 0)
+{
+ ::new(static_cast<void*>(p)) T();
+ using std::swap;
+ swap(*p, x);
+}
+
+/*************************************************************************************************/
+
+/*!
+\ingroup move_related
 \brief Similar to std::uninitialized_copy but
 with move semantics, for movable types.
 */

Modified: sandbox/move/libs/move/test/Jamfile.v2
==============================================================================
--- sandbox/move/libs/move/test/Jamfile.v2 (original)
+++ sandbox/move/libs/move/test/Jamfile.v2 2008-07-13 15:26:36 EDT (Sun, 13 Jul 2008)
@@ -12,6 +12,7 @@
     [ run main.cpp ]
     [ run move.cpp ]
     [ run noncopyable.cpp ]
+ [ run swappable.cpp ]
     [ run move_test.cpp ]
     [ run no_sfinae_test.cpp ]
     [ run has_swap_overload.cpp ]

Modified: sandbox/move/libs/move/test/main.cpp
==============================================================================
--- sandbox/move/libs/move/test/main.cpp (original)
+++ sandbox/move/libs/move/test/main.cpp 2008-07-13 15:26:36 EDT (Sun, 13 Jul 2008)
@@ -48,7 +48,7 @@
     
     // Test is_movable<> template function
 
- BOOST_CHECK(!boost::is_movable<std_vector_t>::value);
+ BOOST_CHECK(boost::is_movable<std_vector_t>::value);
     BOOST_CHECK(boost::is_movable<vector_t>::value);
 
     { // Test move_sink<> via push_back
@@ -123,4 +123,4 @@
 int test_main(int, char**) {
     move_test();
     return 0;
-}
\ No newline at end of file
+}

Modified: sandbox/move/libs/move/test/move.cpp
==============================================================================
--- sandbox/move/libs/move/test/move.cpp (original)
+++ sandbox/move/libs/move/test/move.cpp 2008-07-13 15:26:36 EDT (Sun, 13 Jul 2008)
@@ -144,7 +144,7 @@
     z10 = boost::move(z8);
     
     SAY(" ------ test 25, request move construct from non-movable lvalue ------- ");
- BOOST_STATIC_ASSERT(!boost::is_movable<std::string>::value);
+ BOOST_STATIC_ASSERT(boost::is_movable<std::string>::value);
     std::string s1("hello");
     std::string s2(boost::move(s1));
 

Modified: sandbox/move/libs/move/test/noncopyable.cpp
==============================================================================
--- sandbox/move/libs/move/test/noncopyable.cpp (original)
+++ sandbox/move/libs/move/test/noncopyable.cpp 2008-07-13 15:26:36 EDT (Sun, 13 Jul 2008)
@@ -152,11 +152,6 @@
     SAY(" ------ test 24, move assign from movable lvalue ------- ");
     Y::expect_move();
     z10 = boost::move(z8);
-
- SAY(" ------ test 25, request move construct from non-movable lvalue ------- ");
- BOOST_STATIC_ASSERT(!boost::is_movable<std::string>::value);
- std::string s1("hello");
- std::string s2(boost::move(s1));
 
     SAY("----- done, with " << Y::suboptimal_copies << " suboptimal copies -----");
     return 0;


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