Boost logo

Boost :

Subject: Re: [boost] [Boost.Move] A few notes
From: Dan Ivy (danivy.mail_at_[hidden])
Date: 2012-01-13 10:13:15


On Fri, Jan 13, 2012 at 1:04 AM, Jeffrey Lee Hellrung, Jr.
<jeffrey.hellrung_at_[hidden]> wrote:
> Here's my position:
> - Ideally, client code written for both C++11 and C++03 should not have
> "ugly" workarounds for C++03 deficiencies, and that's basically what
> wrapping all function parameters in some BOOST_MOVE macro (or similar)
> would be, a workaround.

No argument here.

> - If you really want to guarantee C++11-level performance in C++03 and the
> interface can't otherwise guarantee this, and this necessitates some kind
> of workaround, then one workaround (wrapping in a BOOST_MOVE macro) is just
> about as bad as another (storing a temporary and explicitly moving).

Allow me to disagree. I think one altenative is way better than the
other, as it doesn't force you to spread your call expression over
multiple statements, which is, aside from being obscure (BOOST_MOVE is
ugly, but pretty straight-forward), is not applicable in some contexts
(i,e, initializer lists).

>
> In any case, even if we did end up agreeing that wrapping function
> parameters in a BOOST_MOVE macro was desireable, this doesn't entirely
> preclude BOOST_FWD_REF( T ) from expanding to T const &;

That's right, these are two separate things.

 moveable
> temporaries would still be moved. The loss is that const-ness of lvalues is
> not preserved, but that isn't a common case.

Not too common, but far from being a corner case either.

> [...]
>> Interesting. Could you provide a reference or an example?
>
> Here's the idea. In C++11, you can just get away with
> [...]
>

Thanks for expanding. That's a clever trick :). I thought you were
taking about something a bit different though, as this method doesn't
scale to functions taking more than a single parameter (it's
theoretically possible, but not practical), so it's not a general
solution to forwarding.
Btw, if that's all you're trying to do, won't something like this be a
lot simpler?

#include <iostream>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/utility/enable_if.hpp>

template <typename T>
struct movable {};

struct i_can_move : movable<i_can_move> {};

template <typename T>
void what_is(T&) {
    if(!boost::is_const<T>::value)
        std::cout << "modifiable lvalue" << std::endl;
    else
        std::cout << "const lvalue" << std::endl;
}

template <typename T>
typename boost::disable_if<
    boost::is_convertible<T, movable<T> >
>::type what_is(const T&) {
    std::cout << "non-movable const-lvalue "
                 "or rvalue" << std::endl;
}

template <typename T>
void what_is(const movable<T>&) {
    std::cout << "rvalue" << std::endl;
    // No indirect call, and we get to know what T is
}

int main()
{
    {
        i_can_move x;
        const i_can_move y = x;

        what_is(x);
        what_is(y);
        what_is(i_can_move());
    }
    std::cout << std::endl;
    {
        int x;
        const int y = 123;

        what_is(x);
        what_is(y);
        what_is(123);
    }
}

> [...]
>> So, it seems that you're already using the same thing I suggest...
>>
>
> Well, any function using BOOST_FWD2_REF in its parameter list is only
> passed parameters that are lvalues or the result of a boost::forward. So, I
> guess I'm using the same thing, but it doesn't sound like it's in the same
> context...?

But since we only have one BOOST_FWD_REF, I belive it should be
applicable to any context (and you belive that it should be
"optimized" for the most common one, point is clear, let's not open
that again ;) )


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