Issue 2033: Preconditions of reserve, shrink_to_fit, and resize functions (original) (raw)
This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++14 status.
2033. Preconditions of reserve, shrink_to_fit, and resize functions
Section: 23.3.13.3 [vector.capacity], 23.3.5.3 [deque.capacity] Status: C++14 Submitter: Nikolay Ivchenkov Opened: 2011-02-20 Last modified: 2016-01-28
Priority: Not Prioritized
View other active issues in [vector.capacity].
View all other issues in [vector.capacity].
View all issues with C++14 status.
Discussion:
I have several questions with regard to the working paper N3225 (C++0x working draft):
- Where the working draft specifies preconditions for
shrink_to_fitmember function ofstd::vectorandstd::deque? - Where the working draft specifies preconditions for '
void reserve(size_type n)' member function ofstd::vector? - Does a call to '
void resize(size_type sz)' ofstd::vectorrequire the element type to beDefaultConstructible? If yes, why such requirement is not listed in the Requires paragraph? - Does a call to '
void resize(size_type sz)' ofstd::vectorrequire the element type to beMoveAssignablebecause the callerase(begin() + sz, end())mentioned in the Effects paragraph would require the element type to beMoveAssignable? - Why
CopyInsertablerequirement is used for 'void resize(size_type sz)' ofstd::vectorinstead ofMoveInsertablerequirement?
[2011-06-12: Daniel comments and provides wording]
According to my understanding of the mental model of vector (and to some parts for deque) the some requirements are missing in the standard as response to above questions:
- The preconditions of
shrink_to_fitfor bothstd::vectorandstd::dequeshould impose theMoveInsertablerequirements. The reason for this is, that these containers can host move-only types. For a container typeXthe C++03 idiomX(*this).swap(*this)imposes theCopyInsertablerequirements which would make the function call ill-formed, which looks like an unacceptable restriction to me. Assuming the committee decides to support the move-only case, further wording has to be added for the situation where such a move-only type could throw an exception, because this can leave the object in an unspecified state. This seems consistent with the requirements ofreserve, which seems like a very similar function to me (forvector). And this brings us smoothly to the following bullet: - I agree that we are currently missing to specify the preconditions of the
reservefunction. My interpretation of the mental model of this function is that it should work for move-only types, which seems to be supported by the wording used in 23.3.13.3 [vector.capacity] p2:[…] If an exception is thrown other than by the move constructor of a non-CopyInsertable type, there are no effects.
Given this statement, the appropriate requirement isMoveInsertableinto thevector. - I agree that
vector::resize(size_type)misses to list theDefaultConstructiblerequirements. - Unfortunately the current specification in terms of
eraseimplies theMoveAssignablerequirements. I don't think that this implication is intended. This function requires "append" and "pop-back" effects, respectively, where the former can be realized in terms ofMoveInsertablerequirements. The same fix in regard to usingpop_backinstead oferaseis necessary for the two argument overload ofresizeas well (noMoveAssignableis required). - The
CopyInsertablerequirement is incorrect and should beMoveInsertableinstead.
In addition to above mentioned items, the proposed resolution adds a linear complexity bound for shrink_to_fit and attempts to resolve the related issue 2066(i).
[ 2011 Bloomington ]
Move to Ready.
Note for editor: we do not normally refer to 'linear time' for complexity requirements, but there is agreement that any clean-up of such wording is editorial.
Proposed resolution:
This wording is relative to the FDIS.
- Edit 23.3.5.3 [deque.capacity] as indicated [Remark: The suggested change of p4 is not redundant, because
CopyInsertableis not necessarily a refinement ofMoveInsertablein contrast to the fact thatCopyConstructibleis a refinement ofMoveConstructible]:void resize(size_type sz);
-1- Effects: If
sz <= size(), equivalent tocallingerase(begin() + sz, end());pop_back()size() - sztimes. Ifsize() < sz, appendssz - size()value-initialized elements to the sequence.-2- Requires:
Tshall beMoveInsertableinto*thisandDefaultConstructible.
void resize(size_type sz, const T& c);-3- Effects: If
sz <= size(), equivalent to callingpop_back()size() - sztimes. Ifsize() < sz, appendssz - size()copies ofcto the sequence.if (sz > size())insert(end(), sz-size(), c);else if (sz < size())erase(begin()+sz, end());else; // do nothing-4- Requires:
Tshall beMoveInsertableinto*thisandCopyInsertableinto*this.
void shrink_to_fit();-?- Requires:
Tshall beMoveInsertableinto*this.-?- Complexity: Takes at most linear time in the size of the sequence.
-5- Remarks:
shrink_to_fitis a non-binding request to reduce memory use but does not change the size of the sequence. [ Note: The request is non-binding to allow latitude for implementation-specific optimizations. — end note ] - Edit 23.3.13.3 [vector.capacity] as indicated including edits that also resolve 2066(i)[Remark: The combined listing of
MoveInsertableandCopyInsertablebefore p12 is not redundant, becauseCopyInsertableis not necessarily a refinement ofMoveInsertablein contrast to the fact thatCopyConstructibleis a refinement ofMoveConstructible]:
[…]void reserve(size_type n);
-?- Requires:
Tshall beMoveInsertableinto*this.-2- Effects: A directive that informs a vector of a planned change in size, so that it can manage the storage allocation accordingly. After
reserve(),capacity()is greater or equal to the argument of reserve if reallocation happens; and equal to the previous value ofcapacity()otherwise. Reallocation happens at this point if and only if the current capacity is less than the argument ofreserve(). If an exception is thrown other than by the move constructor of a non-CopyInsertabletype, there are no effects.-3- Complexity: It does not change the size of the sequence and takes at most linear time in the size of the sequence.
-4- Throws:
length_errorifn > max_size().[footnote 266]-5- Remarks: Reallocation invalidates all the references, pointers, and iterators referring to the elements in the sequence. It is guaranteed that no reallocation takes place during insertions that happen after a call to
reserve()until the time when an insertion would make the size of the vector greater than the value ofcapacity().
void shrink_to_fit();-?- Requires:
Tshall beMoveInsertableinto*this.-?- Complexity: Takes at most linear time in the size of the sequence.
-6- Remarks:
shrink_to_fitis a non-binding request to reducecapacity()tosize(). [ Note: The request is non-binding to allow latitude for implementation-specific optimizations. — end note ]If an exception is thrown other than by the move constructor of a non-CopyInsertableTthere are no effects.
[…]
void resize(size_type sz);-9- Effects: If
sz <= size(), equivalent tocallingerase(begin() + sz, end());pop_back()size() - sztimes. Ifsize() < sz, appendssz - size()value-initialized elements to the sequence.-10- Requires:
Tshall be~~Copy~~MoveInsertableinto*thisandDefaultConstructible.-??- Remarks: If an exception is thrown other than by the move constructor of a non-
CopyInsertableTthere are no effects.
void resize(size_type sz, const T& c);-11- Effects: If
sz <= size(), equivalent to callingpop_back()size() - sztimes. Ifsize() < sz, appendssz - size()copies ofcto the sequence.if (sz > size())insert(end(), sz-size(), c);else if (sz < size())erase(begin()+sz, end());else; // do nothing-??- Requires:
Tshall beMoveInsertableinto*thisandCopyInsertableinto*this.-12-
RequiresRemarks: If an exception is thrown other than by the move constructor of a non-CopyInsertableTthere are no effects.