C++98 stated that std::vector elements should have copy-constructors. In C++11 that's no longer the case. Instead, the elements must have move-constructors.
Depending on what you do with std::vector, you may or may not really need to call the copy- or move-constructor, yet only one of them is always formally required by the standard. Why?
Update: Apparently, the premise is incorrect. My confusion stemmed from reading answers such as this.
As implied in the comments, there isn't simply one blanket set of requirements on all objects you store in a vector. Rather, the requirements are placed on specific operations.
Although a number of operations do require than the object type be MoveConstructible
and/or MoveAssignable
, copy construction and copy assignment qualify for meeting that requirement--that is, copy constructible is basically a superset of move constructible and (likewise copy assignment vs. move assignment).
The reverse is not true though. For example, if you use the two argument constructor for a vector:
std::vector<T> vec(n, t);
...then T
must be copy constructible (because it's going to attempt to create n
copies of t
in the vector, and with move construction, it would only be able to create one item).
If you wanted to look at it as an inheritance hierarchy, you could think of copy(assignment|construction) as a derived class, and move(assignment|construction) as the base class, so you can implicitly substitute copying for moving but not vice versa.
There are quite a few cases where requirements on elements of a list
are looser than those on elements of a vector
or deque
(requirements on elements of vector
and deque
are nearly always identical, the sole exceptions of which I'm aware (thanks @yakk) being emplace_back
, which requires MoveConstructible for vector, EmplaceConstructible otherwise and the next item listed below--but note its caveat).
If you use std::vector<x> myvector(i, j);
or myvector.assign(i, j);
, (where i
and j
are iterators) then the requirements on T depend on the class of the iterators--if they're forward iterators, then T only needs to be EmplaceConstructible, otherwise T must be MoveConstructible. Caveat: although this does reflect the current wording in the standard, according to LWG 2266 the restrictions for the constructor are incorrect: they should apply regardless of the iterator category, and apply equally to vector and deque. Some future version of the standard will reflect that, but in real use that's how things already are.
In case anybody cares about why that is, and why the special treatment for non-forward iterators: the problem is that with something like an std::istream_iterator
, there's no way to know ahead of time how many items an iterator range might refer to. With something like random-access iterators, it can simply use j - i
to determine the number of items, make that much space, and insert appropriately. To work efficiently with istream_iterator
s, they normally copy the data to the end of the current collection, then after the entire range has been copied/moved into the collection, use rotate
to move them to the desired location. The extra requirement(s) support using rotate
.
There's one variant of insert
that requires elements to be swappable in addition to (Move|Copy)(Constructible|Assignable) if you're doing the insert into a vector
or deque
(the reasoning here is similar to that given above: for this variant of insert
, elements are actually inserted in one place, and then moved around to get them to where they belong).
Where is it that it states that elements must have move-constructors for std::vector in C++11? A rule like that would break a lot of existing code since existing classes wouldn't necessarily have move constructors. It is probably true that you would need either copy-constructors or if you don't have a copy constructor, then you would be required to at least have a move constructor.