
On Mon, Mar 26, 2012 at 12:42 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> 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<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