Summary: | [C++0x] std::thread does not forward its args as rvalues | ||
---|---|---|---|
Product: | gcc | Reporter: | Jonathan Wakely <redi> |
Component: | libstdc++ | Assignee: | Jonathan Wakely <redi> |
Status: | RESOLVED FIXED | ||
Severity: | normal | Keywords: | rejects-valid |
Priority: | P3 | ||
Version: | 4.7.0 | ||
Target Milestone: | 4.7.0 | ||
Host: | Target: | ||
Build: | Known to work: | ||
Known to fail: | Last reconfirmed: | 2011-07-07 08:33:23 | |
Attachments: | do not use std::bind to implement std::thread |
The same problem exists for std::packaged_task and std::async include <future> struct moveable { moveable() = default; moveable(moveable&&) = default; }; void f(moveable) { } int main() { std::packaged_task<void(moveable)> p(f); p(moveable()); } Same problem for call_once too, basically everywhere that uses INVOKE( DECAY_COPY ( std::forward<Callable>(func)), DECAY_COPY (std::forward<Args>(args))...) I'm going to split out the tuple<decay<F>::type, decay<Args>::type...> from thread::_Impl so it can be reused in <future> and <mutex>, as a really simple one-time use version of _Bind_result that doesn't support is_placeholder or is_bind_expression and forwards everything as rvalues, implementing the INVOKE expression above Author: redi Date: Sat Jul 9 10:13:01 2011 New Revision: 176073 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=176073 Log: 2011-07-09 Jonathan Wakely <jwakely.gcc@gmail.com> PR libstdc++/49668 * include/std/functional (__bind_simple): Define. * include/std/future (_Task_setter): Parameterize by type of result pointer instead of state object. (_S_task_setter): Type deduction helper. (_Task_state): Use _S_task_setter and __bind_simple. (_Deferred_state, _Async_state): Store call wrapper directly not as std::function. Use _S_task_setter and __bind_simple. (_S_make_deferred_state, _S_make_async_state): Type deduction helpers. (async): Use new functions and __bind_simple. * include/std/mutex (call_once): Use __bind_simple. * include/std/thread (thread): Likewise. Remove unused headers. * src/thread.cc: Add header. * testsuite/30_threads/async/49668.cc: New. * testsuite/30_threads/call_once/49668.cc: New. * testsuite/30_threads/thread/cons/49668.cc: New. * testsuite/30_threads/thread/cons/moveable.cc: Remove unused bool. Added: trunk/libstdc++-v3/testsuite/30_threads/async/49668.cc trunk/libstdc++-v3/testsuite/30_threads/call_once/49668.cc trunk/libstdc++-v3/testsuite/30_threads/packaged_task/49668.cc trunk/libstdc++-v3/testsuite/30_threads/thread/cons/49668.cc Modified: trunk/libstdc++-v3/ChangeLog trunk/libstdc++-v3/include/std/functional trunk/libstdc++-v3/include/std/future trunk/libstdc++-v3/include/std/mutex trunk/libstdc++-v3/include/std/thread trunk/libstdc++-v3/src/thread.cc trunk/libstdc++-v3/testsuite/30_threads/thread/cons/moveable.cc fixed for 4.7.0 N.B. first reported in http://gcc.gnu.org/ml/libstdc++/2011-07/msg00006.html |
Created attachment 24702 [details] do not use std::bind to implement std::thread #include <thread> struct moveable { moveable() = default; moveable(moveable&&) = default; }; void f(moveable) { } int main() { std::thread t(f, moveable()); t.join(); } The problem is that std::thread uses std::bind internally and the call wrapper returned by std::bind forwards the bound args as lvalues (this is necessary because the call wrapper could be invoked multiple times, so the arguments cannot be moved from) std::thread doesn't need most of the functionality of std::bind anyway, and using it actually makes this ill-formed because std::bind tries to act on the placeholder: void f(decltype(std::placeholders::_1)); std::thread(t, std::placeholders::_1);