By-ref arguments: is this an inconsistency between std::thread and std::bind?
c++, c++11
Solution
The function object returned by `bind` is designed for reuse (i.e., call be called multiple times); it therefore must pass its bound arguments as lvalues, because you don't want to move from said arguments or later calls would see a moved-from bound argument. (Similarly, you want the function object to be called as an lvalue, too.)
This concern is inapplicable to `std::thread` and friends. The thread function will only be called once, with the provided arguments. It's perfectly safe to move from them because nothing else is going to be looking at them. They are effectively temporary copies, made just for the new thread. Thus the function object is called as an rvalue and the arguments are passed as rvalues.
Problem
`std::bind` and `std::thread` share a few design principles. Since both of them store local objets corresponding to the passed arguments, we need to use either `std::ref` or `std::cref` if reference semantics is desired: ``` void f(int& i, double d) { /*...*/ } void g() { int x = 10; std::bind(f, std::ref(x), _1) (3.14); std::thread t1(f, std::ref(x), 3.14); //... } ``` But I'm intrigued by a recent personal discovery: `std::bind` will allow you to pass a value in the case above, even though this is not what one usually wants. ``` std::bind(f, x, _1) (3.14); // Usually wrong, but valid. ``` However, this is not true for `std::thread`. The following will trigger a compile error. ``` std::thread t2(f, x, 3.14); // Usually wrong and invalid: Error! ``` At first sight I thought this was a compiler bug, but the error is indeed legitimate. It seems that the templated version of `std::thread`'s constructor is not able to correctly deduce the arguments due to the copy decaying requirement (tranforming `int&` in `int`) imposed by 30.3.1.2. The question is: Why not require something similar to `std::bind`'s arguments? Or is this apparent inconsistency intended? Note: Explained why it's not a duplicated in the comment below.