Movatterモバイル変換


[0]ホーム

URL:



This page is a snapshot from the LWG issues list, see theLibrary Active Issues List for more information and the meaning ofC++14 status.

2252. Strong guarantee onvector::push_back() still broken with C++11?

Section: 23.3.13.5[vector.modifiers]Status:C++14Submitter: Nicolai JosuttisOpened: 2013-04-21Last modified: 2016-01-28

Priority:Not Prioritized

View all otherissues in [vector.modifiers].

View all issues withC++14 status.

Discussion:

According to my understanding, the strong guarantee ofpush_back() led to the introduction ofnoexcept and to the typical implementation that vectors usually copy their elements on reallocation unless the move operations of their element type guarantees not to throw.

However, if I read the standard correctly, we still don't give the strong guarantee any more:Yes, 23.2.2[container.requirements.general]/10 specifies:

Unless otherwise specified (see 23.2.4.1, 23.2.5.1, 23.3.3.4, and 23.3.6.5) all container types defined in thisClause meet the following additional requirements:

However, 23.3.13.5[vector.modifiers] specifies for vector modifiers,includingpush_back():

If an exception is thrown other than by the copy constructor, move constructor, assignment operator, or move assignment operator ofT or by anyInputIterator operation there are no effects. If an exception is thrown by the move constructor of a non-CopyInsertableT, the effects are unspecified.

I would interpret this as an "otherwise specified" behavior forpush_back(), saying that the strong guarantee is only given if constructors and assignments do not throw.

That means, the strong guarantee of C++03 is broken with C++11.

In addition to all that 23.2.2[container.requirements.general] p10 b2 doesn't mention the corresponding functionsemplace_back() andemplace_front(). These are similar single-element additions and should provide the samestrong guarantee.

Daniel adds:

It seems the error came in whenN2350andN2345 became accepted and where integrated into the working draftN2369.The merge resulted in a form that changed the previous meaning and as far as I understand it, this effect was not intended.

[2013-09-16, Nico provides concrete wording]

[2013-09-26, Nico improves wording]

The new proposed resolution is driven as follows:

Proposed resolution:

This wording is relative to N3691.

  1. Edit 23.2.2[container.requirements.general] p10 b2 as indicated:

  2. Edit 23.3.5.4[deque.modifiers] as indicated:

    iterator insert(const_iterator position, const T& x);iterator insert(const_iterator position, T&& x);iterator insert(const_iterator position, size_type n, const T& x);template <class InputIterator>  iterator insert(const_iterator position,                  InputIterator first, InputIterator last);iterator insert(const_iterator position, initializer_list<T>);template <class... Args> void emplace_front(Args&&... args);template <class... Args> void emplace_back(Args&&... args);template <class... Args> iterator emplace(const_iterator position, Args&&... args);void push_front(const T& x);void push_front(T&& x);void push_back(const T& x);void push_back(T&& x);

    -1-Effects: An insertion in the middle of the deque invalidates all the iterators and references to elementsof the deque. An insertion at either end of the deque invalidates all the iterators to the deque, but hasno effect on the validity of references to elements of the deque.

    -2-Remarks: If an exception is thrown other than by the copy constructor, move constructor, assignmentoperator, or move assignment operator ofT there are no effects.If an exception is thrown while inserting a single element at either end, there are no effects.IfOtherwise, if an exception is thrown by the moveconstructor of a non-CopyInsertableT, the effects are unspecified.

    -3-Complexity: The complexity is linear in the number of elements inserted plus the lesser of the distancesto the beginning and end of the deque. Inserting a single element either at the beginning or end of adeque always takes constant time and causes a single call to a constructor ofT.

  3. Edit 23.3.13.5[vector.modifiers] as indicated:

    iterator insert(const_iterator position, const T& x);iterator insert(const_iterator position, T&& x);iterator insert(const_iterator position, size_type n, const T& x);template <class InputIterator>  iterator insert(const_iterator position, InputIterator first, InputIterator last);iterator insert(const_iterator position, initializer_list<T>);template <class... Args> void emplace_back(Args&&... args);template <class... Args> iterator emplace(const_iterator position, Args&&... args);void push_back(const T& x);void push_back(T&& x);

    -1-Remarks: Causes reallocation if the new size is greater than the old capacity. If no reallocation happens,all the iterators and references before the insertion point remain valid.If an exception is thrown otherthan by the copy constructor, move constructor, assignment operator, or move assignment operatorofT or by anyInputIterator operation there are no effects.If an exception is thrown while inserting a single element at the end andT isCopyInsertableoris_nothrow_move_constructible<T>::value istrue, there are no effects.IfOtherwise, if an exception is thrown by the moveconstructor of a non-CopyInsertableT, the effects are unspecified.

    -2-Complexity: The complexity is linear in the number of elements inserted plus the distance to the endof the vector.


[8]ページ先頭

©2009-2026 Movatter.jp