In the following code:
struct copy_only
{
copy_only() = default;
copy_only(const copy_only&) = default;
copy_only& operator=(const copy_only&) = default;
copy_only(copy_only&&) = delete;
copy_only& operator=(copy_only&&) = delete;
~copy_only() = default;
};
std::vector<copy_only> v;
copy_only c{};
v.push_back(c);
On MSVC we get the error:
error C2280: 'copy_only::copy_only(copy_only &&)': attempting to reference a deleted function
This comes from within the vector implementation where push_back(const&)
calls emplace_back
implementation:
note: while compiling class template member function 'void std::vector<copy_only,std::allocator<copy_only>>::push_back(const _Ty &)'
note: see reference to function template instantiation '_Ty &std::vector<_Ty,std::allocator<_Ty>>::_Emplace_one_at_back<const _Ty&>(const _Ty &)' being compiled
This compiles with gcc and clang. Is this just a massive MSVC compiler bug on the simplest vector example? Or is there some standard thing that would prevent this usage that gcc and clang are just glossing over?
vector::push_back()
has a Precondition of "T
is Cpp17CopyInsertable into X
", and Cpp17CopyInsertable implies Cpp17MoveInsertable according to [container.alloc.reqmts-2.4]:
T
is Cpp17CopyInsertable intoX
means that, in addition toT
being Cpp17MoveInsertable intoX
, the following expression is well-formed:allocator_traits<A>::construct(m, p, v)
and its evaluation causes the following postcondition to hold: The value of
v
is unchanged and is equivalent to*p
.
Since your class is not Cpp17MoveInsertable and therefore not Cpp17CopyInsertable, which violates the Precondition of push_back()
and leads into undefined behavior.