Boost logo

Boost :

Subject: [boost] [move] pre-review comments
From: Jeffrey Lee Hellrung, Jr. (jhellrung_at_[hidden])
Date: 2010-04-03 01:10:37


I have some (long overdue) comments concerning Ion Gaztanaga's proposed
Boost.Move library.

First, Ion, great job on the documentation and implementation. Both are
very readable and usable.

These comments stem from my own use and perceived deficiencies in the
current state of affairs, but they might also lead to a more complex
library. So take them however you want, and you (Ion) and others may
respond at your own convenience.

In below, when I refer to "C++03 compilers", I mean compilers without
rvalue rferences; when I refer to "C++0x compilers", I mean compilers
that do have rvalue references.

Also, some details are lacking, as I'm writing this kind of haphazardly
and over a couple hours while watching the Jazz-Lakers game...
--------

boost::rv<T>
------------
The library should clearly define what requirements a class needs to
satisfy to work with the library's facilities, specifically when rvalue
references are not available. For C++03 compilers, this will involve
defining boost::rv<T>, conversion operators to boost::rv<T>& and (if
copyable) const boost::rv<T>&, and what constructors and assignment
operators there should be and their semantics. I think this interface
specification is of primary importance, and the remaining facilities are
of secondary importance.

boost::is_movable<T>
--------------------
This should evaluate to a Boost.MPL integral constant, and it should
still work for builtin types (and return false).

BOOST_FWD_REF( T ) / boost::forward<T>(x)
-----------------------------------------
I think there should be 2 forwarding mechanisms. One is BOOST_FWD_REF(
T ) (paired with boost::forward<T>(x)), which expands to const T& on
C++03 compilers and is able to capture rvalues. The other I've called
BOOST_PERFECT_FWD_REF( T ) (paired with boost::perfect_forward<T>(x)),
which expands to T& and will *not* capture rvalues, but will correctly
forward lvalue references to non-const. I'm open to alternative names.
  The intent is that you can use BOOST_PERFECT_FWD_REF( T ) if you know
you will never need to capture rvalues (e.g., it will only receive the
result of a boost::forward or boost::perfect_forward).

I think it might also be useful to provide metafunctions
boost::forward_param<T> and boost::perfect_forward_param<T> that strips
off any {const} boost::rv<T>&'s for use with Boost.ResultOf.

BOOST_MOVABLE_BUT_NOT_COPYABLE / BOOST_COPYABLE_AND_MOVABLE
-----------------------------------------------------------
I don't use these. Instead, I've created no fewer than 10 macros to
enable move emulation, depending on the particular application:

BOOST_BASIC_MOVABLE_COPYABLE( T )
BOOST_MOVABLE_NONCOPYABLE( T )
BOOST_MOVABLE_COPYABLE_DEFINE_COPY_ASSIGN_FROM_MOVE( T )
BOOST_MOVABLE_COPYABLE_DEFINE_COPY_ASSIGN_FROM_SWAP( T )
BOOST_OPTIMAL_MOVABLE_COPYABLE( T )
BOOST_FRIENDLY_MOVABLE_COPYABLE( T )
BOOST_OPTIMAL_MOVABLE_COPYABLE_IF( T, Cond )
BOOST_FRIENDLY_MOVABLE_COPYABLE_IF( T, Cond )
BOOST_OPTIMAL_MOVABLE_COPYABLE_IF_MOVABLE( T, U_seq )
BOOST_FRIENDLY_MOVABLE_COPYABLE_IF_MOVABLE( T, U_seq )

BOOST_BASIC_MOVABLE_COPYABLE provides a move constructor and a move
assignment operator, but does not provide a mechanism to move assign
automatically from rvalues. I typically use this in base classes.

BOOST_MOVABLE_NONCOPYABLE should be self-explanatory.

BOOST_MOVABLE_COPYABLE_DEFINE_COPY_ASSIGN_FROM_MOVE( T ) defines a
by-value copy assignment via copy-and-move. Similarly,
BOOST_MOVABLE_COPYABLE_DEFINE_COPY_ASSIGN_FROM_SWAP( T ) defines a
by-value copy assignment via copy-and-swap. Implementing copy
assignment to receive by value captures rvalues optimally via copy RVO.

BOOST_OPTIMAL_MOVABLE_COPYABLE* and BOOST_FRIENDLY_MOVABLE_COPYABLE*
differ in how rvalues are captured for assignment on C++03 compilers.
OPTIMAL declares an operator=(T&) that forwards to the copy assignment
operator, and an operator=(const rv<T>&) to move assign. As has been
discussed previously, this has undesirable consequences if you rely on
the compiler to generate the copy assignment operator in a class
enclosing an "optimal movable" type. FRIENDLY declares an operator=(T)
(on C++03 compilers) and implements it in terms of the move assignment
operator. On C++0x compilers, both use an operator=(T&&) and
operator(const &).

BOOST_*_MOVABLE_COPYABLE_IF( T, Cond ) enables movability if Cond is
true, and does not define a move constructor and move assignment
operator if Cond is false. Similarly,
BOOST_*_MOVABLE_COPYABLE_IF_MOVABLE( T, U_seq ) will enable movability
if any type in the Boost.PP seq U_seq is movable (as determined by
boost::is_movable).

"The rest of the stuff"
-----------------------
I'd consider iterator's and algorithm extensions to be of tertiary
importance, and I haven't yet used them.

- Jeff


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