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())
}
The reason this fails is because when you specify
foo<Movable>, the function you're binding to is:However, the value passed by
std::bindwill not be an rvalue, but an lvalue (stored as a member somewhere in the resultingbindfunctor). That, is the generated functor is akin to:Constructed as
your_bind(Movable()). So you can see this fails becauseMovable&&cannot bind toMovable.†A simple solution might be this instead:
Because now the function you're calling is:
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:That is, we just
std::movethe argument before we make the call, so it can bind. But yikes, that's ugly. The cast is required becausestd::moveis 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::movewasn't overloaded, as if we had something like: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&&, whereTis a template parameter, can be deduced to anything, if you let it be.)