There are two existing questions about replacing vector elements that are not assignable:
A typical reason for an object to be non-assignable is that its class definition includes const
members and therefore has its operator=
deleted.
std::vector
requires that its element type be assignable. And indeed, at least using GCC, neither direct assignment (vec[i] = x;
), nor a combination of erase()
and insert()
to replace an element works when the object is not assignable.
Can a function like the following, which uses vector::data()
, direct element destruction, and placement new with the copy constructor, be used to replace the element without causing undefined behaviour?
template <typename T>
inline void replace(std::vector<T> &vec, const size_t pos, const T& src)
{
T *p = vec.data() + pos;
p->~T();
new (p) T(src);
}
An example of the function in use is found below. This compiles in GCC 4.7 and appears to work.
struct A
{
const int _i;
A(const int &i):_i(i) {}
};
int main() {
std::vector<A> vec;
A c1(1);
A c2(2);
vec.push_back(c1);
std::cout << vec[0]._i << std::endl;
/* To replace the element in the vector
we cannot use this: */
//vec[0] = c2;
/* Nor this: */
//vec.erase(begin(vec));
//vec.insert(begin(vec),c2);
/* But this we can: */
replace(vec,0,c2);
std::cout << vec[0]._i << std::endl;
return 0;
}
vector
still calls the assignment operator and not your replace function. – Primulaceousconst
members is rarely a good idea in C++. Why does your class haveconst
members? – Russellrussetis_nothrow_copy_constructible
) – Diopsidepush_back
is about making a copy into an new slot, not overriding an old one. – Diopsideconst
member in classX
, you cannot assign to variables of typeX
anymore (because variables are nothing more than named objects in C++), and that's rarely what people want. – Russellrussetvector
must be copyable. And it's definitely an antipattern, in that it isn't exception safe, and will raise havoc in the case of inheritance. If you want to support assignment, support assignment. – Bailiwickvec[i] = x
to replace the object at the ith slot with x (rather than to copy the contents ofx
over the contents of the object at the ith slot) is perhaps rooted in the idea to viewvec[i]
as the ith slot (and not the object stored at the ith slot). So it's a reference-way of looking at things, not a value-way. – Midweekg++ -D_GLIBCXX_CONCEPT_CHECKS
. (At one point, it was the intent to require this to fail to compiler. This was deferred since concepts didn't make it into this release, but I would expect it to be the case in the next version of the standard.) – Bailiwick