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.
From 30.3.1.2, paragraph 3 and 4 of N3337:
template <class F, class ...Args> explicit thread(F&& f, Args&&... args);
Requires:
F
and eachTi
inArgs
shall satisfy theMoveConstructible
requirements.INVOKE (DECAY_-COPY ( std::forward<F>(f)), DECAY_COPY (std::forward<Args>(args))...)
(20.8.2) shall be a valid expression.Effects: Constructs an object of type thread. The new thread of execution executes
INVOKE (DECAY_-COPY ( std::forward<F>(f)), DECAY_COPY (std::forward<Args>(args))...)
with the calls toDECAY_COPY
being evaluated in the constructing thread. Any return value from this invocation is ignored. [ Note: This implies that any exceptions not thrown from the invocation of the copy off
will be thrown in the constructing thread, not the new thread. —end note ] If the invocation ofINVOKE (DECAY_COPY ( std::forward<F>(f)), DECAY_COPY (std::forward<Args>(args))...)
terminates with an uncaught exception, std::terminate shall be called.
So yes, this should work. If it doesn't, then that's a bug in your implementation.