
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