Passing rvalues through std::bind

c++, c++11, rvalue, rvalue-reference, std

Solution

The reason this fails is because when you specify `foo<Movable>`, the function you're binding to is:

void foo(Movable&&) // *must* be an rvalue
{
}

However, the value passed by `std::bind` will not be an rvalue, but an lvalue (stored as a member somewhere in the resulting `bind` functor). That, is the generated functor is akin to:

struct your_bind
{
    your_bind(Movable arg0) :
    arg0(arg0)
    {}

    void operator()()
    {
        foo<int>(arg0); // lvalue!
    }

    Movable arg0;
};

Constructed as `your_bind(Movable())`. So you can see this fails because `Movable&&` cannot bind to `Movable`.†

A simple solution might be this instead:

auto f = std::bind(foo<Movable&>, Movable());

Because now the function you're calling is:

void foo(Movable& /* conceptually, this was Movable& &&
                        and collapsed to Movable& */)
{
}

And the call works fine (and, of course, you could make that `foo<const Movable&>` if desired). But an interesting question is if we can get your original bind to work, and we can via:

auto f = std::bind(foo<Movable>,
            std::bind(static_cast<Movable&&(&)(Movable&)>(std::move<Movable&>),
                Movable()));

That is, we just `std::move` the argument before we make the call, so it can bind. But yikes, that's ugly. The cast is required because `std::move` is an overloaded function, so we have to specify which overload we want by casting to the desired type, eliminating the other options.

It actually wouldn't be so bad if `std::move` wasn't overloaded, as if we had something like:

Movable&& my_special_move(Movable& x)
{
    return std::move(x);
}


auto f = std::bind(foo<Movable>, std::bind(my_special_move, Movable()));

Which is much simpler. But unless you have such a function laying around, I think it's clear you probably just want to specify a more explicit template argument.

† This is different than calling the function without an explicit template argument, because explicitly specifying it removes the possibility for it to be deduced. (`T&&`, where `T` is a template parameter, can be deduced to anything, if you let it be.)

Problem

I want to pass an rvalue through `std::bind` to a function that takes an rvalue reference in C++0x. I can't figure out how to do it. For example: ``` #include <utility> #include <functional> template<class Type> void foo(Type &&value) { Type new_object = std::forward<Type>(value); // move-construct if possible } class Movable { public: Movable(Movable &&) = default; Movable &operator=(Movable &&) = default; }; int main() { auto f = std::bind(foo<Movable>, Movable()); f(); // error, but want the same effect as foo(Movable()) } ```

Original source

Related problems