Why this code won't compile if destructor is declared?

c++, c++11

Solution

(Answer taken from comments, no credit taken by me)

If a destructor is declared manually, the default move constructor is not created when compiling. Forcing the default move constructor to be used will fix this:

A(A&& o) = default;

Problem

Consider the following C++11 code: ``` #include <thread> #include <vector> struct A { A() {} //virtual ~A() = default; //~A() = default; //~A() {}; std::thread t; }; int main() { std::vector<A> v; v.emplace_back(); } ``` If any of the lines declaring the destructor on the previous code is uncommented, this code won't compile. The compiler complains about copy construtor of `std::thread` being deleted. But `std::vector::emplace_back` should make no use of copy constructor, so, why it fails? And why the heck the mention of the destructor matters? GCC output (`~A() {};` uncommented): ``` $ g++ --std=c++11 -o test test.cpp In file included from /usr/include/c++/4.8/memory:64:0, from /usr/include/c++/4.8/thread:40, from test.cpp:1: /usr/include/c++/4.8/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = A; _Args = {A}]’: /usr/include/c++/4.8/bits/stl_uninitialized.h:75:53: required from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<A*>; _ForwardIterator = A*; bool _TrivialValueTypes = false]’ /usr/include/c++/4.8/bits/stl_uninitialized.h:117:41: required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<A*>; _ForwardIterator = A*]’ /usr/include/c++/4.8/bits/stl_uninitialized.h:258:63: required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::move_iterator<A*>; _ForwardIterator = A*; _Tp = A]’ /usr/include/c++/4.8/bits/stl_uninitialized.h:281:69: required from ‘_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = A*; _ForwardIterator = A*; _Allocator = std::allocator<A>]’ /usr/include/c++/4.8/bits/vector.tcc:415:43: required from ‘void std::vector<_Tp, _Alloc>::_M_emplace_back_aux(_Args&& ...) [with _Args = {}; _Tp = A; _Alloc = std::allocator<A>]’ /usr/include/c++/4.8/bits/vector.tcc:101:54: required from ‘void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {}; _Tp = A; _Alloc = std::allocator<A>]’ test.cpp:17:17: required from here /usr/include/c++/4.8/bits/stl_construct.h:75:7: error: use of deleted function ‘A::A(const A&)’ { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); } ^ test.cpp:4:8: note: ‘A::A(const A&)’ is implicitly deleted because the default definition would be ill-formed: struct A { ^ test.cpp:4:8: error: use of deleted function ‘std::thread::thread(const std::thread&)’ In file included from test.cpp:1:0: /usr/include/c++/4.8/thread:126:5: error: declared here thread(const thread&) = delete; ^ ``` Clang output (`~A() {};` uncommented): ``` $ clang++ --std=c++11 -o test test.cpp In file included from test.cpp:1: In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/thread:40: In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/memory:64: /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_construct.h:75:38: error: call to implicitly-deleted copy constructor of 'A' { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); } ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~ /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_uninitialized.h:75:8: note: in instantiation of function template specialization 'std::_Construct<A, A>' requested here std::_Construct(std::__addressof(*__cur), *__first); ^ /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_uninitialized.h:117:2: note: in instantiation of function template specialization 'std::__uninitialized_copy<false>::__uninit_copy<std::move_iterator<A *>, A *>' requested here __uninit_copy(__first, __last, __result); ^ /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_uninitialized.h:258:19: note: in instantiation of function template specialization 'std::uninitialized_copy<std::move_iterator<A *>, A *>' requested here { return std::uninitialized_copy(__first, __last, __result); } ^ /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_uninitialized.h:279:19: note: in instantiation of function template specialization 'std::__uninitialized_copy_a<std::move_iterator<A *>, A *, A>' requested here return std::__uninitialized_copy_a ^ /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/vector.tcc:413:15: note: in instantiation of function template specialization 'std::__uninitialized_move_if_noexcept_a<A *, A *, std::allocator<A> >' requested here = std::__uninitialized_move_if_noexcept_a ^ /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/vector.tcc:101:4: note: in instantiation of function template specialization 'std::vector<A, std::allocator<A> >::_M_emplace_back_aux<>' requested here _M_emplace_back_aux(std::forward<_Args>(__args)...); ^ test.cpp:17:4: note: in instantiation of function template specialization 'std::vector<A, std::allocator<A> >::emplace_back<>' requested here v.emplace_back(); ^ test.cpp:11:14: note: copy constructor of 'A' is implicitly deleted because field 't' has a deleted copy constructor std::thread t; ^ /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/thread:126:5: note: 'thread' has been explicitly marked deleted here thread(const thread&) = delete; ^ 1 error generated. ```

Original source