The following program doesn’t build in VS11 beta, gcc 4.5, or clang 3.1
#include <thread>
#include <memory>
int main() {
std::unique_ptr<int> p;
std::thread th([](std::unique_ptr<int>) {
},std::move(p));
th.join();
}
This is because the argument type is not copyable, but the implementation attempts to copy it.
As far as I can tell, this program is well formed and should work. The requirements for std::thread seem to imply that movable, non-copyable arguments should work here. Specifically it says that the callable object and each argument shall satisfy the MoveConstructible requirements, and that INVOKE(DECAY_COPY(std::forward<F>(f)),DECAY_COPY(std::forward<Args>(args))...) shall be a valid expression.
In this case I think expression works out to something like:
template <class T> typename std::decay<T>::type decay_copy(T&& v)
{ return std::forward<T>(v); }
std::unique_ptr<int> p;
auto f = [](std::unique_ptr<int>) {};
decay_copy(f)(decay_copy(std::move(p)));
And I don’t think this is supposed to involve a copy of p. gcc at least can compile this expression, though VS11 does not.
- Am I wrong about the requirements and the arguments must be copyable?
- Does the standard leave any leeway on this issue for implementations to copy arguments?
- Or are the implementation I tried non-conforming?
From 30.3.1.2, paragraph 3 and 4 of N3337:
So yes, this should work. If it doesn’t, then that’s a bug in your implementation.
Do note that any parameter movement/copying will happen on the new thread. You’re passing references to another thread, so you need to make sure that they still exist until that thread starts.