Boost logo

Boost Users :

Subject: Re: [Boost-users] [Review] Formal Review: Boost.Move
From: Ion Gaztañaga (igaztanaga_at_[hidden])
Date: 2010-05-24 17:09:58


On 24/05/2010 17:16, Steven Watanabe wrote:
> AMDG
>
> Ion Gaztañaga wrote:
>> This does not seem to work:
>>
>> template<class T>
>> struct rv_ref
>> {
>> rv_ref(T &t){ ptr = &t; }
>> rv_ref(const T &t){ ptr = &t; }
>
> These constructors need to be explicit.
>
> Your code compiles with VC 2010 with this change.

But not on my GCC:

error: no matching function for call to 'movable::movable(movable)'
note: candidates are: movable::movable(rv_ref<movable>)
note: movable::movable(movable&)
error: initializing temporary from result of
'movable::movable(rv_ref<movable>)'

But after some strange experiments, and fighting against the elements
here's my last try, compiles in MSVC 7.1, 8.0, 9.0, 10.0, gcc 4.3, and
Intel 10.0 (edg based). Keep an eye on the catch by non-const reference,
plus enable_if trick, to avoid conversion ambiguities:

#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>

#define BOOST_COPYABLE_AND_MOVABLE(TYPE)\
    public:\
    TYPE& operator=(TYPE &t)\
    {\
       this->operator=(const_cast<const TYPE &>(t));\
       return *this; \
    }\
    public:\
    operator rv_ref<TYPE>(){ return rv_ref<TYPE>(*this); }\
    private:\
//

#define BOOST_COPY_ASSIGN_REF(TYPE)\
    const_rv_ref< TYPE > \
//

#define BOOST_MOVABLE_BUT_NOT_COPYABLE(TYPE)\
    private:\
    TYPE(TYPE &);\
    TYPE& operator=(TYPE &);\
    public:\
    operator rv_ref<TYPE>(){ return rv_ref<TYPE>(*this); }\
    private:\
//

#define BOOST_RV_REF(TYPE)\
    rv_ref<TYPE> \
//

template<class T>
struct rv_ref
{
    explicit rv_ref(T &t){ ptr = &t; }

    operator T& () { return *ptr; }

    private:
    T *ptr;
};

template<class T>
struct const_rv_ref
{
    const_rv_ref(rv_ref<T> t){ ptr = t.ptr; }
    template<class U>
    const_rv_ref(U &t, typename boost::enable_if_c
       <boost::is_same<const T, U>::value>::type* = 0)
    { ptr = &t; }
    operator const T& () const { return this->get(); }

    private:
    const T *ptr;
};

template<class T>
inline rv_ref<T> move(T &t)
{ return static_cast< rv_ref<T> >(t); }

class copiable_and_movable
{
    public:
    BOOST_COPYABLE_AND_MOVABLE(copiable_and_movable)
    public:
    copiable_and_movable(){}

    copiable_and_movable(const copiable_and_movable &){}
    copiable_and_movable(BOOST_RV_REF(copiable_and_movable)){}

    copiable_and_movable &operator =
       (BOOST_COPY_ASSIGN_REF(copiable_and_movable)){ return *this; }
    copiable_and_movable &operator =
       (BOOST_RV_REF(copiable_and_movable)){ return *this; }
};

static copiable_and_movable scm;

copiable_and_movable sc_rvalue()
{ return copiable_and_movable(); }

const copiable_and_movable sc_crvalue()
{
    typedef const copiable_and_movable ctype;
    return ctype();
}

const copiable_and_movable &sc_clvalue()
{ return scm; }

copiable_and_movable &sc_lvalue()
{ return scm; }

class movable
{
    BOOST_MOVABLE_BUT_NOT_COPYABLE(movable)

    public:
    movable() : i(0) {}

    movable(BOOST_RV_REF(movable) rv)
    {
       movable &t = rv;
       i = t.i;
       t.i = 0;
    }

    movable& operator=(BOOST_RV_REF(movable) rv)
    {
       movable &t = rv;
       i = t.i;
       t.i = 0;
       return *this;
    }
    int i;
};

movable sm_rvalue()
{
    movable m;
//This fails in several compilers (GCC for instance)
// error: no matching function for call to 'movable::movable(movable)'
// note: candidates are: movable::movable(rv_ref<movable>)
// note: movable::movable(movable&)
// initializing temporary from result of 'movable::movable(rv_ref<movable>)'
//
// --> return move(m);

    //This works (in-place construction of movable)
    return movable(move(m));
}

const int rvalue_catched = 1;
const int lvalue_catched = 2;
const int const_rlvalue_catched = 3;

int catch_it(BOOST_RV_REF(copiable_and_movable))
{ return rvalue_catched; }

int catch_it(copiable_and_movable &)
{ return lvalue_catched; }

int catch_it(BOOST_COPY_ASSIGN_REF(copiable_and_movable))
{ return const_rlvalue_catched; }

int main()
{
    {
       movable m, m2(move(m));
       m = move(m2);
       m = sm_rvalue();
    }
    {
       copiable_and_movable c, c2(move(c));
       c = move(c2);
       c = sc_rvalue();
       c = sc_clvalue();
       c = sc_lvalue();
    }

    if(rvalue_catched != catch_it(sc_rvalue()))
       return 1;
    if(lvalue_catched != catch_it(sc_lvalue()))
       return 1;
    if(const_rlvalue_catched != catch_it(sc_clvalue()))
       return 1;
    if(const_rlvalue_catched != catch_it(sc_crvalue()))
       return 1;

    return 0;
}


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net