resize
Section: 23.3.11.3 [vector.capacity] Status: C++17 Submitter: Daniel Krügler Opened: 2012-06-07 Last modified: 2017-07-30
Priority: 1
View other active issues in [vector.capacity].
View all other issues in [vector.capacity].
View all issues with C++17 status.
Discussion:
As part of resolving LWG issue 2033 a wording change was done for resize()
to
respect the problem mentioned in the question:
Does a call to 'void resize(size_type sz)' of
std::vector
require the element type to beMoveAssignable
because the callerase(begin() + sz, end())
mentioned in the Effects paragraph would require the element type to beMoveAssignable
?
The wording change was to replace in 23.3.5.3 [deque.capacity] and 23.3.11.3 [vector.capacity]:
-1- Effects: If
sz <= size()
, equivalent toerase(begin() + sz, end())
; […]
by:
-1- Effects: If
sz <= size()
, equivalent to callingpop_back() size() - sz
times. […]
The overlooked side-effect of this wording change is that this implies a destruction order
of the removed elements to be in reverse order of construction, but the previous version
did not impose any specific destruction order due to the way how the semantics of erase
is specified in Table 100.
#include <vector>
#include <iostream>
struct Probe {
int value;
Probe() : value(0) {}
Probe(int value) : value(value) {}
~Probe() { std::cout << "~Probe() of " << value << std::endl; }
};
int main() {
std::vector<Probe> v;
v.push_back(Probe(1));
v.push_back(Probe(2));
v.push_back(Probe(3));
std::cout << "---" << std::endl;
v.resize(0);
}
the last three lines of the output for every compiler I tested was:
~Probe() of 1 ~Probe() of 2 ~Probe() of 3
but a conforming implementation would now need to change this order to
~Probe() of 3 ~Probe() of 2 ~Probe() of 1
This possible stringent interpretation makes sense, because one can argue that sequence containers
(or at least std::vector
) should have the same required destruction order of it's elements,
as elements of a C array or controlled by memory deallocated with an array delete
have.
I also learned that libc++ does indeed implement std::vector::resize
in a way that the
second output form is observed.
std::vector
this was not required in C++03 and this request may be too strong. My current
suggestion would be to restore the effects of the previous wording in regard to the destruction order,
because otherwise several currently existing implementations would be broken just because of this
additional requirement.
[2013-03-15 Issues Teleconference]
Moved to Open.
Jonathan says that he believes this is a valid issue.
Walter wonders if this was intended when we made the previous change - if so, this would be NAD.
Jonathan said that Issue 2033 doesn't mention ordering.
Walter then asked if anyone is really unhappy that we're destroying items in reverse order of construction.
Jonathan points out that this conflicts with existing practice (libstc++, but not libc++).
Jonathan asked for clarification as to whether this change was intended by 2033.
[2014-06 Rapperswil]
Daniel points out that the ordering change was not intended.
General agreement that implementations should not be required to change.[2014-06-28 Daniel provides alternative wording]
[Urbana 2014-11-07: Move to Ready]
Proposed resolution:
This wording is relative to N3936.
Change 23.3.5.3 [deque.capacity] as indicated: [Drafting note: The chosen wording form is similar to that for
forward_list
. Note that the existing Requires element already specifies the necessary operational requirements
on the value type. — end drafting note]
void resize(size_type sz);-1- Effects: If
[…]sz <
, erases the last=size()size() - sz
elements from the sequenceequivalent to calling. Otherwisepop_back() size() - sz
timesIf, appendssize() <= sz
sz - size()
default-inserted elements to the sequence.void resize(size_type sz, const T& c);-3- Effects: If
[…]sz <
, erases the last=size()size() - sz
elements from the sequenceequivalent to calling. Otherwisepop_back() size() - sz
timesIf, appendssize() < sz
sz - size()
copies ofc
to the sequence.
Change 23.3.11.3 [vector.capacity] as indicated: [Drafting note: See deque
for the rationale of the
used wording. — end drafting note]
void resize(size_type sz);-12- Effects: If
[…]sz <
, erases the last=size()size() - sz
elements from the sequenceequivalent to calling. Otherwisepop_back() size() - sz
timesIf, appendssize() < sz
sz - size()
default-inserted elements to the sequence.void resize(size_type sz, const T& c);-15- Effects: If
[…]sz <
, erases the last=size()size() - sz
elements from the sequenceequivalent to calling. Otherwisepop_back() size() - sz
timesIf, appendssize() < sz
sz - size()
copies ofc
to the sequence.