Passing arguments to std::async by reference fails

asynchronous, c++, c++11, multithreading

Solution

It's a deliberate design choice/trade-off.

First, it's not necessarily possible to find out whether the functionoid passed to `async` takes its arguments by reference or not. (If it's not a simple function but a function object, it could have an overloaded function call operator, for example.) So `async` cannot say, "Hey, let me just check what the target function wants, and I'll do the right thing."

So the design question is, does it take all arguments by reference if possible (i.e. if they're lvalues), or does it always make copies? Making copies is the safe choice here: a copy cannot become dangling, and a copy cannot exhibit race conditions (unless it's really weird). So that's the choice that was made: all arguments are copied by default.

But then, the mechanism is written so that it actually fails to then pass the arguments to a non-const lvalue reference parameter. That's another choice for safety: otherwise, the function that you would expect to modify your original lvalue instead modifies the copy, leading to bugs that are very hard to track down.

But what if you really, really want the non-const lvalue reference parameter? What if you promise to watch out for dangling references and race conditions? That's what `std::ref` is for. It's an explicit opt-in to the dangerous reference semantics. It's your way of saying, "I know what I'm doing here."

Problem

I've noticed that it's impossible to pass a non-const reference as an argument to `std::async`. ``` #include <functional> #include <future> void foo(int& value) {} int main() { int value = 23; std::async(foo, value); } ``` My compiler (GCC 4.8.1) gives the following error for this example: ``` error: no type named ‘type’ in ‘class std::result_of<void (*(int))(int&)>’ ``` But if I wrap the value passed to `std::async` in `std::reference_wrapper`, everything is OK. I assume this is because `std::async` takes it's arguments by value, but I still don't understand the reason for the error.

Original source