
Anthony Williams wrote:
Ion Gaztañaga <igaztanaga@gmail.com> writes:
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.
This is almost identical to the boost.thread move emulation. In Boost.thread, rv<T> is boost::detail::thread_move_t<T>, but most of the other stuff is equivalent.
I was having some problems with some of Interprocess movable classes and Visual 7.1. I just changed is_movable conversion check from T& -> rv<T> to T -> rv<T> and my problems disappeared. I don't know if that would break some existing code, though: template<class T> class is_movable { public: static const bool value = boost::is_convertible<T, detail::rv<T> >::value; };
If there is support for this as a basis for combined support, I can easily rework boost.thread to use it.
That's the idea. I attach a newer version that uses the modified is_movable trait, pushes rv to namespace detail and uses boost::addressof() to implement operator ->(). 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_MOVE_HPP #define BOOST_MOVE_HPP #ifndef BOOST_HAS_RVALUE_REFS #ifndef BOOST_NO_SFINAE #include <boost/utility/enable_if.hpp> #endif #include <boost/utility/addressof.hpp> #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 namespace detail { template<class T> class rv { private: rv &operator=(const rv&); T& r_; public: explicit rv(T& r) : r_(r) {} T* operator->() {return boost::addressof(r_);} T& operator*() {return r_;} }; } //namespace detail template<class T> class is_movable { public: static const bool value = boost::is_convertible<T, detail::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(detail::rv<T>(t)); } #endif template<typename T> detail::rv<T> move(detail::rv<T> t) { return t; } #define BOOST_ENABLE_MOVE_EMULATION(TYPE)\ operator boost::detail::rv<TYPE>() \ { return boost::detail::rv<TYPE>(*this); }\ // #define BOOST_SWAP_BASED_MOVE_ASSIGN(TYPE)\ TYPE& operator=(boost::detail::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 { #endif //#ifndef BOOST_MOVE_HPP