Inspired by this comment about binding lambdas with rvalue reference parameters directly to std::async
, binding an rvalue to a lambda through std::async
compiles and executes as expected: (live example)
auto lambda = [] (std::string&& message) {
std::cout << message << std::endl;
};
auto future = std::async(lambda, std::string{"hello world"});
future.get();
Using std::bind
, however, triggers a compiler error: (live example)
auto lambda = [] (std::string&& message) {
std::cout << message << std::endl;
};
auto bound = std::bind(lambda, std::string{"hello world"}); // Compiler error
bound();
This is because std::bind
keeps message
as an lvalue, so that when it passes it to the lambda, the argument no longer matches the parameter.
I've read that std::async
internally uses std::bind
, so how does it get away with rvalue reference parameters when std::bind
does not? Is there a particular part of the standard that requires this behavior or is this dependent on the compiler?
I've read that
std::async
internally usesstd::bind
, so how does it get away with rvalue reference parameters whenstd::bind
does not?
It doesn't use bind
internally. (Or rather, it couldn't without going through some epic contortions like the one in @Praetorian's answer in that question, and it's much easier to just write something separately).
It is usually implemented using a somewhat bind
-like machinery, but it's much simpler because it doesn't have to handle all sorts of weird things bind
handles (nested bind
s, placeholders, dropping extra arguments, etc.)
Is there a particular part of the standard that requires this behavior or is this dependent on the compiler?
It's required by the standard. The specification of bind
is ridiculously dense, but does require plain bound arguments to be passed as lvalues ([func.bind.bind]/p10, bullet 4).
async
is specified to call INVOKE (DECAY_COPY (std::forward<F>(f)),
DECAY_COPY (std::forward<Args>(args))...)
, and DECAY_COPY
always returns an rvalue.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With