For reasons I do not fully understand, std::vector<std::unique_future<T>>'s push_back fails because it attempts to use the (deleted) copy constructor and (copying) assignment operator. The std::vector implementation seems to support move-only objects in C++0x mode, and I don't really see why that is not working here. $ g++-4.5-20091112 -v Using built-in specs. COLLECT_GCC=/usr/local/bin/g++-4.5-20091112 COLLECT_LTO_WRAPPER=/usr/local/gcc-4.5-20091112/libexec/gcc/x86_64-unknown-linux-gnu/4.5.0/lto-wrapper Target: x86_64-unknown-linux-gnu Configured with: ../gcc-4.5-20091112/configure --prefix=/usr/local/gcc-4.5-20091112 --program-suffix=-4.5-20091112 --enable-languages=c,c++ Thread model: posix gcc version 4.5.0 20091112 (experimental) (GCC)
Created attachment 19165 [details] Test case Here is the full output compiling this on my machine: $ g++-4.5-20091112 -Wall -W -std=c++0x movable.cpp -o move In file included from /usr/local/gcc-4.5-20091112/lib/gcc/x86_64-unknown-linux-gnu/4.5.0/../../../../include/c++/4.5.0/vector:69:0, from movable.cpp:1: /usr/local/gcc-4.5-20091112/lib/gcc/x86_64-unknown-linux-gnu/4.5.0/../../../../include/c++/4.5.0/future: In member function 'void std::vector<_Tp, _Alloc>::_M_insert_aux(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {std::unique_future<int>}, _Tp = std::unique_future<int>, _Alloc = std::allocator<std::unique_future<int> >, std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<std::unique_future<int>*, std::vector<std::unique_future<int> > >, typename std::vector<_Tp, _Alloc>::_Base::_Tp_alloc_type::pointer = std::unique_future<int>*]': /usr/local/gcc-4.5-20091112/lib/gcc/x86_64-unknown-linux-gnu/4.5.0/../../../../include/c++/4.5.0/bits/vector.tcc:100:4: instantiated from 'void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {std::unique_future<int>}, _Tp = std::unique_future<int>, _Alloc = std::allocator<std::unique_future<int> >]' /usr/local/gcc-4.5-20091112/lib/gcc/x86_64-unknown-linux-gnu/4.5.0/../../../../include/c++/4.5.0/bits/stl_vector.h:747:9: instantiated from 'void std::vector<_Tp, _Alloc>::push_back(value_type&&) [with _Tp = std::unique_future<int>, _Alloc = std::allocator<std::unique_future<int> >, value_type = std::unique_future<int>]' movable.cpp:12:50: instantiated from here /usr/local/gcc-4.5-20091112/lib/gcc/x86_64-unknown-linux-gnu/4.5.0/../../../../include/c++/4.5.0/future:440:22: error: deleted function 'std::unique_future<_Res>& std::unique_future<_Res>::operator=(const std::unique_future<_Res>&) [with _Res = int]' /usr/local/gcc-4.5-20091112/lib/gcc/x86_64-unknown-linux-gnu/4.5.0/../../../../include/c++/4.5.0/bits/vector.tcc:314:4: error: used here In file included from /usr/local/gcc-4.5-20091112/lib/gcc/x86_64-unknown-linux-gnu/4.5.0/../../../../include/c++/4.5.0/vector:61:0, from movable.cpp:1: /usr/local/gcc-4.5-20091112/lib/gcc/x86_64-unknown-linux-gnu/4.5.0/../../../../include/c++/4.5.0/future: In static member function 'static _BI2 std::__copy_move_backward<true, false, std::random_access_iterator_tag>::__copy_move_b(_BI1, _BI1, _BI2) [with _BI1 = std::unique_future<int>*, _BI2 = std::unique_future<int>*]': /usr/local/gcc-4.5-20091112/lib/gcc/x86_64-unknown-linux-gnu/4.5.0/../../../../include/c++/4.5.0/bits/stl_algobase.h:596:18: instantiated from '_BI2 std::__copy_move_backward_a(_BI1, _BI1, _BI2) [with bool _IsMove = true, _BI1 = std::unique_future<int>*, _BI2 = std::unique_future<int>*]' /usr/local/gcc-4.5-20091112/lib/gcc/x86_64-unknown-linux-gnu/4.5.0/../../../../include/c++/4.5.0/bits/stl_algobase.h:606:45: instantiated from '_BI2 std::__copy_move_backward_a2(_BI1, _BI1, _BI2) [with bool _IsMove = true, _BI1 = std::unique_future<int>*, _BI2 = std::unique_future<int>*]' /usr/local/gcc-4.5-20091112/lib/gcc/x86_64-unknown-linux-gnu/4.5.0/../../../../include/c++/4.5.0/bits/stl_algobase.h:677:56: instantiated from '_BI2 std::move_backward(_BI1, _BI1, _BI2) [with _BI1 = std::unique_future<int>*, _BI2 = std::unique_future<int>*]' /usr/local/gcc-4.5-20091112/lib/gcc/x86_64-unknown-linux-gnu/4.5.0/../../../../include/c++/4.5.0/bits/vector.tcc:308:4: instantiated from 'void std::vector<_Tp, _Alloc>::_M_insert_aux(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {std::unique_future<int>}, _Tp = std::unique_future<int>, _Alloc = std::allocator<std::unique_future<int> >, std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<std::unique_future<int>*, std::vector<std::unique_future<int> > >, typename std::vector<_Tp, _Alloc>::_Base::_Tp_alloc_type::pointer = std::unique_future<int>*]' /usr/local/gcc-4.5-20091112/lib/gcc/x86_64-unknown-linux-gnu/4.5.0/../../../../include/c++/4.5.0/bits/vector.tcc:100:4: instantiated from 'void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {std::unique_future<int>}, _Tp = std::unique_future<int>, _Alloc = std::allocator<std::unique_future<int> >]' /usr/local/gcc-4.5-20091112/lib/gcc/x86_64-unknown-linux-gnu/4.5.0/../../../../include/c++/4.5.0/bits/stl_vector.h:747:9: instantiated from 'void std::vector<_Tp, _Alloc>::push_back(value_type&&) [with _Tp = std::unique_future<int>, _Alloc = std::allocator<std::unique_future<int> >, value_type = std::unique_future<int>]' movable.cpp:12:50: instantiated from here /usr/local/gcc-4.5-20091112/lib/gcc/x86_64-unknown-linux-gnu/4.5.0/../../../../include/c++/4.5.0/future:440:22: error: deleted function 'std::unique_future<_Res>& std::unique_future<_Res>::operator=(const std::unique_future<_Res>&) [with _Res = int]' /usr/local/gcc-4.5-20091112/lib/gcc/x86_64-unknown-linux-gnu/4.5.0/../../../../include/c++/4.5.0/bits/stl_algobase.h:561:6: error: used here
The issue is pretty simple, actually: std::unique_future (which, by the way, will be renamed just std::future), is missing move assignment operator. Note, in N2914 it does *not* exist, has been added only in N3000, I guess we can as well add it right now, before the rename. But again, consider that these facilities are still experimental, the working draft is changing rather quickly...
(In reply to comment #2) > The issue is pretty simple, actually: std::unique_future (which, by the way, > will be renamed just std::future), is missing move assignment operator. Note, > in N2914 it does *not* exist, has been added only in N3000, I guess we can as > well add it right now, before the rename. But again, consider that these > facilities are still experimental, the working draft is changing rather > quickly... I've already done most of the changes to update <future> to n3000, including adding move assignment, I just need to adjust the tests because lots of the old behaviour that was tested has changed (e.g. no default construction)
I think Jon can take this, for the std::future work.
I'm planning to send a patch for feedback in the next 48 hours, including everything except atomic_future, because I think we need to implement [util.smartptr.shared.atomic] to support atomic_future
Jon, what do you think, shall we go ahead with this one too?
I was going to ask you the same thing :-) I would like to update <future> for 4.5, I'll send the patch when I get home in a few hours
Great.
patch posted as http://gcc.gnu.org/ml/gcc-patches/2010-01/msg01126.html
Subject: Bug 42201 Author: redi Date: Thu Jan 21 00:01:47 2010 New Revision: 156097 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=156097 Log: 2010-01-21 Jonathan Wakely <jwakely.gcc@gmail.com> PR libstdc++/42201 * include/std/future: Update to latest WP. * src/functexcept.cc (__throw_future_error): Use make_error_code. * testsuite/30_threads/async/any.cc: New. * testsuite/30_threads/async/async.cc: New. * testsuite/30_threads/async/sync.cc: New. * testsuite/30_threads/packaged_task/cons/alloc.cc: New. * testsuite/30_threads/packaged_task/cons/assign_neg.cc: Adjust. * testsuite/30_threads/packaged_task/cons/copy_neg.cc: Adjust. * testsuite/30_threads/packaged_task/members/get_future.cc: Adjust. * testsuite/30_threads/packaged_task/members/get_future2.cc: Likewise. * testsuite/30_threads/packaged_task/members/invoke.cc: Adjust. * testsuite/30_threads/packaged_task/members/invoke2.cc: Adjust. * testsuite/30_threads/packaged_task/members/invoke3.cc: Adjust. * testsuite/30_threads/packaged_task/members/invoke4.cc: Adjust. * testsuite/30_threads/packaged_task/members/reset.cc: Adjust. * testsuite/30_threads/packaged_task/members/reset2.cc: Adjust. * testsuite/30_threads/shared_future/cons/assign_neg.cc: Remove. * testsuite/30_threads/shared_future/cons/default_neg.cc: Remove. * testsuite/30_threads/shared_future/cons/default.cc: New. * testsuite/30_threads/shared_future/cons/assign.cc: New. * testsuite/30_threads/shared_future/cons/copy.cc: Adjust. * testsuite/30_threads/shared_future/cons/move.cc: Adjust. * testsuite/30_threads/shared_future/cons/move_assign.cc: New. * testsuite/30_threads/shared_future/members/is_ready.cc: Remove. * testsuite/30_threads/shared_future/members/has_value.cc: Remove. * testsuite/30_threads/shared_future/members/has_exception.cc: Remove. * testsuite/30_threads/shared_future/members/valid.cc: New. * testsuite/30_threads/unique_future/cons/default_neg.cc: Remove. * testsuite/30_threads/unique_future/cons/default.cc: New. * testsuite/30_threads/unique_future/cons/move_assign.cc: New. * testsuite/30_threads/unique_future/cons/assign_neg.cc: Adjust. * testsuite/30_threads/unique_future/cons/copy_neg.cc: Adjust. * testsuite/30_threads/unique_future/cons/move.cc: Adjust. * testsuite/30_threads/unique_future/requirements/ explicit_instantiation.cc: Adjust. * testsuite/30_threads/unique_future/members/is_ready.cc: Remove. * testsuite/30_threads/unique_future/members/has_value.cc: Remove. * testsuite/30_threads/unique_future/members/has_exception.cc: Remove. * testsuite/30_threads/unique_future/members/valid.cc: New. * testsuite/30_threads/unique_future/members/get.cc: Adjust. * testsuite/30_threads/unique_future/members/get2.cc: Adjust. * testsuite/30_threads/unique_future/members/wait.cc: Adjust. * testsuite/30_threads/unique_future/members/wait_for.cc: Adjust. * testsuite/30_threads/unique_future/members/wait_until.cc: Adjust. * testsuite/30_threads/headers/future/types_std_c++0x.cc: Adjust. * testsuite/30_threads/promise/cons/alloc.cc: New. * testsuite/30_threads/promise/cons/assign_neg.cc: Adjust. * testsuite/30_threads/promise/cons/copy_neg.cc: Adjust. * testsuite/30_threads/promise/cons/move.cc: Adjust. * testsuite/30_threads/promise/cons/move_assign.cc: Adjust. * testsuite/30_threads/promise/members/get_future.cc: Adjust. * testsuite/30_threads/promise/members/set_value.cc: Adjust. * testsuite/30_threads/promise/members/set_exception.cc: Adjust. * testsuite/30_threads/promise/members/set_exception2.cc: Adjust. * testsuite/30_threads/promise/members/set_value2.cc: Adjust. * testsuite/30_threads/promise/members/set_value3.cc: Adjust. * testsuite/30_threads/promise/members/swap.cc: Adjust. Added: trunk/libstdc++-v3/testsuite/30_threads/async/ trunk/libstdc++-v3/testsuite/30_threads/async/any.cc trunk/libstdc++-v3/testsuite/30_threads/async/async.cc trunk/libstdc++-v3/testsuite/30_threads/async/sync.cc trunk/libstdc++-v3/testsuite/30_threads/packaged_task/cons/alloc.cc trunk/libstdc++-v3/testsuite/30_threads/promise/cons/alloc.cc trunk/libstdc++-v3/testsuite/30_threads/shared_future/cons/assign.cc trunk/libstdc++-v3/testsuite/30_threads/shared_future/cons/default.cc trunk/libstdc++-v3/testsuite/30_threads/shared_future/cons/move_assign.cc trunk/libstdc++-v3/testsuite/30_threads/shared_future/members/valid.cc trunk/libstdc++-v3/testsuite/30_threads/unique_future/cons/default.cc trunk/libstdc++-v3/testsuite/30_threads/unique_future/cons/move_assign.cc trunk/libstdc++-v3/testsuite/30_threads/unique_future/members/valid.cc Removed: trunk/libstdc++-v3/testsuite/30_threads/shared_future/cons/assign_neg.cc trunk/libstdc++-v3/testsuite/30_threads/shared_future/cons/default_neg.cc trunk/libstdc++-v3/testsuite/30_threads/shared_future/members/has_exception.cc trunk/libstdc++-v3/testsuite/30_threads/shared_future/members/has_value.cc trunk/libstdc++-v3/testsuite/30_threads/shared_future/members/is_ready.cc trunk/libstdc++-v3/testsuite/30_threads/unique_future/cons/default_neg.cc trunk/libstdc++-v3/testsuite/30_threads/unique_future/members/has_exception.cc trunk/libstdc++-v3/testsuite/30_threads/unique_future/members/has_value.cc trunk/libstdc++-v3/testsuite/30_threads/unique_future/members/is_ready.cc Modified: trunk/libstdc++-v3/ChangeLog trunk/libstdc++-v3/include/std/future trunk/libstdc++-v3/src/functexcept.cc trunk/libstdc++-v3/testsuite/30_threads/headers/future/types_std_c++0x.cc trunk/libstdc++-v3/testsuite/30_threads/packaged_task/cons/assign_neg.cc trunk/libstdc++-v3/testsuite/30_threads/packaged_task/cons/copy_neg.cc trunk/libstdc++-v3/testsuite/30_threads/packaged_task/members/get_future.cc trunk/libstdc++-v3/testsuite/30_threads/packaged_task/members/get_future2.cc trunk/libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke.cc trunk/libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke2.cc trunk/libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke3.cc trunk/libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke4.cc trunk/libstdc++-v3/testsuite/30_threads/packaged_task/members/reset.cc trunk/libstdc++-v3/testsuite/30_threads/packaged_task/members/reset2.cc trunk/libstdc++-v3/testsuite/30_threads/promise/cons/assign_neg.cc trunk/libstdc++-v3/testsuite/30_threads/promise/cons/copy_neg.cc trunk/libstdc++-v3/testsuite/30_threads/promise/cons/move.cc trunk/libstdc++-v3/testsuite/30_threads/promise/cons/move_assign.cc trunk/libstdc++-v3/testsuite/30_threads/promise/members/get_future.cc trunk/libstdc++-v3/testsuite/30_threads/promise/members/set_exception.cc trunk/libstdc++-v3/testsuite/30_threads/promise/members/set_exception2.cc trunk/libstdc++-v3/testsuite/30_threads/promise/members/set_value.cc trunk/libstdc++-v3/testsuite/30_threads/promise/members/set_value2.cc trunk/libstdc++-v3/testsuite/30_threads/promise/members/set_value3.cc trunk/libstdc++-v3/testsuite/30_threads/promise/members/swap.cc trunk/libstdc++-v3/testsuite/30_threads/shared_future/cons/copy.cc trunk/libstdc++-v3/testsuite/30_threads/shared_future/cons/move.cc trunk/libstdc++-v3/testsuite/30_threads/unique_future/cons/assign_neg.cc trunk/libstdc++-v3/testsuite/30_threads/unique_future/cons/copy_neg.cc trunk/libstdc++-v3/testsuite/30_threads/unique_future/cons/move.cc trunk/libstdc++-v3/testsuite/30_threads/unique_future/members/get.cc trunk/libstdc++-v3/testsuite/30_threads/unique_future/members/get2.cc trunk/libstdc++-v3/testsuite/30_threads/unique_future/members/wait.cc trunk/libstdc++-v3/testsuite/30_threads/unique_future/members/wait_for.cc trunk/libstdc++-v3/testsuite/30_threads/unique_future/members/wait_until.cc trunk/libstdc++-v3/testsuite/30_threads/unique_future/requirements/explicit_instantiation.cc
Fixed. The testcase works if you replace unique_future with future.