Reputation: 91
#include <deque>
#include <vector>
struct A
{
A(int* const p) : m_P(p) {}
A(A&& rhs) : m_P(rhs.m_P) { rhs.m_P = nullptr; }
A& operator=(A&& rhs) { delete m_P; m_P = rhs.m_P; rhs.m_P = nullptr; }
~A() { delete m_P; }
A(A const& rhs) = delete;
A& operator=(A const& rhs) = delete;
int* m_P;
};
int main()
{
#ifdef DDDEQUE
std::vector<std::pair<int, std::deque<A> > > vd;
vd.emplace(vd.end(), 1, std::deque<A>());
#endif // #ifdef DDDEQUE
std::vector<std::pair<int, std::vector<A> > > vv;
vv.emplace(vv.end(), 1, std::vector<A>());
}
If compiling with g++ 4.8.5, 5.2.0, 5.3.0 and -DDDDEQUE
I get a verbose error message ending with
.../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)...); }
^
gcc.cpp:11:5: note: declared here
A(A const& rhs) = delete;
without -D...
compiles OK.
With VC2015, VC2012 both versions compile OK.
Does deque
(but not vector
) need the copy constructor for gcc?
Upvotes: 2
Views: 2107
Reputation: 30604
This appears to be specific to libstdc++ (gcc); given the code below;
struct A
{
A() {};
A(A&&) noexcept { }
A& operator=(A&&) noexcept { return *this; }
~A() { }
};
int main()
{
std::vector<A> a;
a.push_back(A{}); // or emplace(a.end()... etc.
std::vector<std::deque<A>> b;
b.push_back(std::deque<A>());
std::vector<std::pair<int,A>> c;
c.push_back(std::pair<int,A>{});
std::vector<std::pair<int,std::deque<A>>> d;
d.push_back(std::pair<int,std::deque<A>>{});
}
G++ fails to compile b
, and d
, clang compiles all 4 (except possibly d
depending on the version of libc++ used) and MSVC compiles all 4 cases (using their own associated standard library; with libstdc++, clang also fails b
and d
).
Does
deque
(but notvector
) need the copy constructor for gcc?
It appears as though, yes gcc does still require the copy constructor.
In more formal terms; in C++03 std::deque
required the type used in the container to be Copy Constructible and Copy Assignable. This changed in C++11, the requirements were relaxed, albeit a complete type is generally still required - given the OP sample, your standard library still requires the copy construction and assignment.
From the linked reference;
T
- The type of the elements.
T
must meet the requirements of CopyAssignable and CopyConstructible. (until C++11)The requirements that are imposed on the elements depend on the actual operations performed on the container. Generally, it is required that element type is a complete type and meets the requirements of Erasable, but many member functions impose stricter requirements. (since C++11)
Upvotes: 3