|
Boost : |
Subject: Re: [boost] [move] Unifying move emulation code in boost
From: Ion Gaztañaga (igaztanaga_at_[hidden])
Date: 2009-01-05 08:46:19
Anthony Williams wrote:
> Ion Gaztañaga <igaztanaga_at_[hidden]> 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
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk