Boost logo

Boost :

Subject: Re: [boost] [move] explicit moving from a rvalue
From: Jeffrey Lee Hellrung, Jr. (jeffrey.hellrung_at_[hidden])
Date: 2012-03-27 11:01:24


On Mon, Mar 26, 2012 at 12:42 PM, Vicente J. Botet Escriba <
vicente.botet_at_[hidden]> wrote:

> Hi Ion,
>
> With the current emulation of move semantics of Boost.Thread using
> Boost.move, I have a case that I would like to make working in a portable
> way
>
> boost::thread t = boost::thread( MoveOnly());
>
> The library declares the template move constructor from a movable callable
> as as follows
>
> template <class F>
> explicit thread(boost::rv<F>& f);
>
> and MoveOnly is declared as defined below.
>
> The problem is a know limitation as the compiler is unable to deduce F as
> been MoveOnly even if MoveOnly is convertible to boost::rv<MoveOnly>&
> Jeffrey Lee Hellrung, Jr. made a proposal to try to solve the issue, but
> his proposal has a performance penality.
>

Agreed, although I would think a sufficiently advanced and aggressive
compiler could optimize the type erasure away.

Here it is a less elegant but efficient enough alternative. The addition of
> a explicit move conversion as
>
> ::boost::rv<MoveOnly>& move()
> {
> return *static_cast< ::boost::rv<MoveOnly>* >(this);
> }
>
> allows to the following to work as expected
>
> boost::thread t = boost::thread( MoveOnly().move());
>
> While this workaround works when we are using the emulation it doesn't
> works when rvalue references are supported.
>
> I have defined a macro BOOST_EXPLICIT_MOVE that allows to write portable
> code
>
> #if ! defined BOOST_NO_RVALUE_REFERENCES
> #define BOOST_MOVE(RVALUE) RVALUE
> #else
> #define BOOST_MOVE(RVALUE) RVALUE.move()
> #endif
>
> that can be used as
>
> boost::thread t = boost::thread( BOOST_MOVE(MoveOnly()));
>
> The move() function is not really needed as the macro can hide the needed
> conversion, but could be preferred by users that don't need to make
> portable programs.
>

I played around with such a macro (essentially wrapping the argument in an
explicit cast if it was an rvalue of move-emulation-enabled type), but
haven't used it extensively. Hiding everything behind the macro
implementation, I think, is preferable to adding to the move emulation
interface. In any case, I question whether use of such a macro will catch
on. It's...ugly :/

> The evident liability is of course the use of the macro. Is there
> something wrong on this design, something to to improve?
>
> The same design can be used on compilers, such as as SunStudio (see
> https://svn.boost.org/trac/**boost/ticket/6222>),
> that prefer the overload of a private copy constructor to an public move
> constructor. On these kind of compilers the following overload
>
> private:
> MoveOnly(MoveOnly&);
> public
> MoveOnly(boost::rv<MoveOnly>&)
>
> makes the following to fail at compile time
>
> MoveOnly MakeMoveOnly() {
> return MoveOnly();
> }
>
> but
>
> MoveOnly( MakeMoveOnly(() {
> return BOOST_MOVE(MoveOnly());
> }
>
> will work.
>
> Do you think that member functions as the explicit move() and a macro as
> BOOST_MOVE can be added to Boost.Move emulation?
>

The macro sounds plausible to me; I'm not convinced of the need for the
move member function.

Best,
> Vicente
>
> /////////////////////////////
>
[...]

- Jeff


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk