
Hi, Howard's unique_ptr contribution has shown again the need for a unified move emulation in Boost. We already have move emulation at least in 5 libraries: -> Interprocess: based on sandbox boost.move library, return types are wrapped in a move_return type. -> Unordered: based on Adobe's move library. It's more advanced than the previous one, but Adobe's own library says (http://stlab.adobe.com/group__move__related.html) that a Movable type must satisfy the requirements of concept Regular, which has copy constructor (thus disabling move-only types!). I don't know if the move emulation itself uses Regular requirements. -> Thread: similar to Howard's unique_ptr move emulation code, user code never sees move_xxx or similar classes. -> Ptr_container: a simple emulation used for static_move_ptr, that could be replaced with a boost::unique_ptr class. -> Variant: MOJO-based emulation (similar to the one used by Interprocess). I think it can be easily replaced with unique_ptr-style emulation. We've been waiting the move library for months, but the fact is that we can't continue having ad-hoc solutions for each library. boost::thread objects must be stored somewhere and unordered containers and boost::interprocess containers are already move-aware. I want to make Intrusive also move-aware but I won't do it until there is some general consensus on what's the common move emulation. I think code changes in boost::thread and boost::unordered would be minimal if we adopt a solution similar to the one used by Howard's unique_ptr. Interprocess changes are heavier but I'm reading to adapt the library to that solution. I've written (attached) a small, surely not complete, but usable boost/move.hpp header (ok, it could go to boost/detail/move.hpp until a decent review is done) that is tested with a movable class in the file movable_test.cpp, both with Visual 7.1 and move-enabled GCC 4.3. The goal of this post is to know if that header file would be enough for all current libraries using move emulation. I have more suggestions (new traits like has_trivial_destructor_after_move<>...) but the main question is if that header can be used to agree a common protocol between us. It would be really nice if we could rework our code for Boost 1.39. If the header contains enough for everyone, I'm ready to write some documentation and tests. I know that this Move library is not what many expect (common macros and utilities to write the same code for rvalue-enabled and older compilers) but I'm afraid entropy has already grown too much ;-) and we can't continue waiting while we add more and more emulation code to Boost. Regards, Ion // 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) // (C) Copyright 2007-8 Anthony Williams // (C) Copyright 2009 Howard Hinnant // (C) Copyright 2009 Ion Gaztanaga #include <boost/config.hpp> #include <boost/type_traits/is_convertible.hpp> #ifndef BOOST_HAS_RVALUE_REFS #ifndef BOOST_NO_SFINAE #include <boost/utility/enable_if.hpp> #endif #else //#ifndef BOOST_HAS_RVALUE_REFS #include <boost/type_traits/remove_reference.hpp> #endif namespace boost { #include <boost/config/abi_prefix.hpp> #ifndef BOOST_HAS_RVALUE_REFS template<class T> class rv { private: rv &operator=(const rv&); T& r_; public: explicit rv(T& r) : r_(r) {} T* operator->() {return &r_;} T& operator*() {return r_;} }; template<class T> class is_movable { public: static const bool value = boost::is_convertible<T&, rv<T> >::value; }; #ifndef BOOST_NO_SFINAE template<typename T> typename boost::enable_if<boost::is_movable<T>, T>::type move(T& t) { return T(rv<T>(t)); } #endif template<typename T> rv<T> move(rv<T> t) { return t; } #define BOOST_ENABLE_MOVE_EMULATION(TYPE)\ operator boost::rv<TYPE>() \ { return boost::rv<TYPE>(*this); }\ // #define BOOST_SWAP_BASED_MOVE_ASSIGN(TYPE)\ TYPE& operator=(boost::rv<TYPE> r) \ { \ TYPE tmp(r); \ this->swap(tmp); \ return *this; \ } \ // #else //#ifndef BOOST_HAS_RVALUE_REFS #define BOOST_ENABLE_MOVE_EMULATION(TYPE)\ // #define BOOST_SWAP_BASED_MOVE_ASSIGN(TYPE)\ TYPE& operator=(TYPE &&r) \ { \ TYPE tmp(boost::move(r)); \ this->swap(tmp); \ return *this; \ } \ // template <class T> struct move_identity_type { typedef T type; }; template <class T> inline T&& forward(typename boost::move_identity_type<T>::type&& t) { return t; } template <class T> inline typename boost::remove_reference<T>::type&& move(T&& t) { return t; } template <class T, class U> class move_is_convertible { typedef char true_t; class false_t { char dummy[2]; }; static true_t dispatch(U); static false_t dispatch(...); static T trigger(); public: enum { value = sizeof(dispatch(trigger())) == sizeof(true_t) }; }; template<class T> class is_movable { public: static const bool value = move_is_convertible<T&&, T>::value; }; #endif //#ifndef BOOST_HAS_RVALUE_REFS #include <boost/config/abi_suffix.hpp> } //namespace boost {