I have a class whose copy constructors are explicitly deleted (because A uses pointers internally and I don't want to fall into shallow copy pitfalls):
class A { public: A(const A&) = delete; A& operator=(const A&) = delete; A(const B& b, const C& c); }
Now I have a vector of type vector<A> aVector;
and I want to insert elements into it - so I use emplace_back
:
aVector.emplace_back(b, c);
However, this fails to compile using gcc and I get the error -
third-party/gcc-4.7.1-glibc-2.14.1/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/bits/stl_construct.h: In instantiation of 'void std::_Construct(_T1*, _Args&& ...) third-party/gcc-4.7.1-glibc-2.14.1/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/bits/stl_uninitialized.h:77:3: required from 'static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) third-party/gcc-4.7.1-glibc-2.14.1/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/bits/stl_uninitialized.h:119:41: required from '_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) third-party/gcc-4.7.1-glibc-2.14.1/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/bits/stl_uninitialized.h:260:63: required from '_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) third-party/gcc-4.7.1-glibc-2.14.1/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/bits/stl_uninitialized.h:283:67: required from '_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) third-party/gcc-4.7.1-glibc-2.14.1/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/bits/vector.tcc:410:6: required from 'void std::vector<_Tp, _Alloc>::_M_emplace_back_aux(_Args&& ...) third-party/gcc-4.7.1-glibc-2.14.1/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/bits/vector.tcc:102:4: required from 'void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...)
What is the reason for this error and how can it be fixed without removing the deletion of the copy constructors? Do I need a move constructor - does it need to be explicitly defined?
If you dereference the pointer and push the result onto a std::vector<T> , then a copy of the object is made. Collections always make copies.
The default copy constructor will copy all members – i.e. call their respective copy constructors. So yes, a std::vector (being nothing special as far as C++ is concerned) will be duly copied.
It is necessary to pass object as reference and not by value because if you pass it by value its copy is constructed using the copy constructor. This means the copy constructor would call itself to make copy. This process will go on until the compiler runs out of memory.
If you need a "dynamic" array, then std::vector is the natural solution. It should in general be the default container for everything. But if you want a statically sized array created at time of compilation (like a C-style array is) but wrapped in a nice C++ object then std::array might be a better choice.
You should add move constructor - because std::vector::emplace_back
may do relocation which requires copy/move constructor. Or just use std::deque
.
LIVE DEMO
#include <vector> #include <deque> using namespace std; struct NoCopyNoMove { NoCopyNoMove(const NoCopyNoMove&) = delete; NoCopyNoMove& operator=(const NoCopyNoMove&) = delete; NoCopyNoMove(NoCopyNoMove&&) = delete; NoCopyNoMove& operator=(NoCopyNoMove&&) = delete; NoCopyNoMove(int){}; }; struct OnlyMove { OnlyMove(const OnlyMove&) = delete; OnlyMove& operator=(const OnlyMove&) = delete; OnlyMove(OnlyMove&&) noexcept {} OnlyMove& operator=(OnlyMove&&) noexcept {} OnlyMove(int){}; }; int main() { deque<NoCopyNoMove> x; x.emplace_back(1); vector<OnlyMove> y; y.emplace_back(1); }
§ 23.2.3 Table 101 — Optional sequence container operations
a.emplace_back(args)
[...]Requires:
T
shall beEmplaceConstructible
intoX
from args. Forvector
,T
shall also beMoveInsertable
intoX
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With