Section: 23.2.4 [sequence.reqmts] Status: C++11 Submitter: Andrew Koenig Opened: 1999-06-28 Last modified: 2016-11-12
Priority: Not Prioritized
View other active issues in [sequence.reqmts].
View all other issues in [sequence.reqmts].
View all issues with C++11 status.
Discussion:
Suppose that c and c1 are sequential containers and i is an iterator that refers to an element of c. Then I can insert a copy of c1's elements into c ahead of element i by executing
c.insert(i, c1.begin(), c1.end());
If c is a vector, it is fairly easy for me to find out where the newly inserted elements are, even though i is now invalid:
size_t i_loc = i - c.begin(); c.insert(i, c1.begin(), c1.end());
and now the first inserted element is at c.begin()+i_loc and one
past the last is at c.begin()+i_loc+c1.size().
But what if c is a list? I can still find the location of one
past the last inserted element, because i is still valid.
To find the location of the first inserted element, though,
I must execute something like
for (size_t n = c1.size(); n; --n) --i;
because i is now no longer a random-access iterator.
Alternatively, I might write something like
bool first = i == c.begin(); list<T>::iterator j = i; if (!first) --j; c.insert(i, c1.begin(), c1.end()); if (first) j = c.begin(); else ++j;
which, although wretched, requires less overhead.
But I think the right solution is to change the definition of insert
so that instead of returning void, it returns an iterator that refers
to the first element inserted, if any, and otherwise is a copy of its
first argument.
[ Summit: ]
Reopened by Alisdair.
[ Post Summit Alisdair adds: ]
In addition to the original rationale for C++03, this change also gives a consistent interface for all container insert operations i.e. they all return an iterator to the (first) inserted item.
Proposed wording provided.
[ 2009-07 Frankfurt ]
Q: why isn't this change also proposed for associative containers?
A: The returned iterator wouldn't necessarily point to a contiguous range.
Moved to Ready.
Proposed resolution:
23.2.4 [sequence.reqmts] Table 83
change return type from void
to iterator
for the following rows:
Table 83 — Sequence container requirements (in addition to container) Expression Return type Assertion/note pre-/post-condition a.insert(p,n,t)
voiditeratorInserts n
copies oft
beforep
.a.insert(p,i,j)
voiditeratorEach iterator in the range [i,j)
shall be dereferenced exactly once. pre:i
andj
are not iterators intoa
. Inserts copies of elements in[i, j)
beforep
a.insert(p,il)
voiditeratora.insert(p, il.begin(), il.end())
.
Add after p6 23.2.4 [sequence.reqmts]:
-6- ...
The iterator returned from
a.insert(p,n,t)
points to the copy of the first element inserted intoa
, orp
ifn == 0
.The iterator returned from
a.insert(p,i,j)
points to the copy of the first element inserted intoa
, orp
ifi == j
.The iterator returned from
a.insert(p,il)
points to the copy of the first element inserted intoa
, orp
ifil
is empty.
p2 23.3.5 [deque] Update class definition, change return type
from void
to iterator
:
voiditerator insert(const_iterator position, size_type n, const T& x); template <class InputIterator>voiditerator insert(const_iterator position, InputIterator first, InputIterator last);voiditerator insert(const_iterator position, initializer_list<T>);
23.3.5.4 [deque.modifiers] change return type from void
to iterator
on following declarations:
voiditerator insert(const_iterator position, size_type n, const T& x); template <class InputIterator>voiditerator insert(const_iterator position, InputIterator first, InputIterator last);
Add the following (missing) declaration
iterator insert(const_iterator position, initializer_list<T>);
[forwardlist] Update class definition, change return type
from void
to iterator
:
voiditerator insert_after(const_iterator position, initializer_list<T> il);voiditerator insert_after(const_iterator position, size_type n, const T& x); template <class InputIterator>voiditerator insert_after(const_iterator position, InputIterator first, InputIterator last);
p8 [forwardlist.modifiers] change return type from void
to iterator
:
voiditerator insert_after(const_iterator position, size_type n, const T& x);
Add paragraph:
Returns: position.
p10 [forwardlist.modifiers] change return type from void
to iterator
:
template <class InputIterator>voiditerator insert_after(const_iterator position, InputIterator first, InputIterator last);
Add paragraph:
Returns: position.
p12 [forwardlist.modifiers] change return type from void
to iterator
on following declarations:
voiditerator insert_after(const_iterator position, initializer_list<T> il);
change return type from void
to iterator
on following declarations:
p2 23.3.9 [list] Update class definition, change return type from void
to iterator
:
voiditerator insert(const_iterator position, size_type n, const T& x); template <class InputIterator>voiditerator insert(const_iterator position, InputIterator first, InputIterator last);voiditerator insert(const_iterator position, initializer_list<T>);
23.3.9.4 [list.modifiers] change return type from void
to iterator
on following declarations:
voiditerator insert(const_iterator position, size_type n, const T& x); template <class InputIterator>voiditerator insert(const_iterator position, InputIterator first, InputIterator last);
Add the following (missing) declaration
iterator insert(const_iterator position, initializer_list<T>);
p2 23.3.11 [vector]
Update class definition, change return type from void
to iterator
:
voiditerator insert(const_iterator position, T&& x);voiditerator insert(const_iterator position, size_type n, const T& x); template <class InputIterator>voiditerator insert(const_iterator position, InputIterator first, InputIterator last);voiditerator insert(const_iterator position, initializer_list<T>);
23.3.11.5 [vector.modifiers] change return type from void
to iterator
on following declarations:
voiditerator insert(const_iterator position, size_type n, const T& x); template <class InputIterator>voiditerator insert(const_iterator position, InputIterator first, InputIterator last);
Add the following (missing) declaration
iterator insert(const_iterator position, initializer_list<T>);
p1 23.3.12 [vector.bool] Update class definition, change return type from void
to iterator
:
voiditerator insert (const_iterator position, size_type n, const bool& x); template <class InputIterator>voiditerator insert(const_iterator position, InputIterator first, InputIterator last);voiditerator insert(const_iterator position, initializer_list<bool> il);
p5 27.4.3 [basic.string] Update class definition, change return type from void
to iterator
:
voiditerator insert(const_iterator p, size_type n, charT c); template<class InputIterator>voiditerator insert(const_iterator p, InputIterator first, InputIterator last);voiditerator insert(const_iterator p, initializer_list<charT>);
p13 27.4.3.7.4 [string.insert] change return type from void
to iterator
:
voiditerator insert(const_iterator p, size_type n, charT c);
Add paragraph:
Returns: an iterator which refers to the copy of the first inserted character, or
p
ifn == 0
.
p15 27.4.3.7.4 [string.insert] change return type from void
to iterator
:
template<class InputIterator>voiditerator insert(const_iterator p, InputIterator first, InputIterator last);
Add paragraph:
Returns: an iterator which refers to the copy of the first inserted character, or
p
iffirst == last
.
p17 27.4.3.7.4 [string.insert] change return type from void
to iterator
:
voiditerator insert(const_iterator p, initializer_list<charT> il);
Add paragraph:
Returns: an iterator which refers to the copy of the first inserted character, or
p
ifil
is empty.
Rationale:
[ The following was the C++98/03 rationale and does not necessarily apply to the proposed resolution in the C++0X time frame: ]
The LWG believes this was an intentional design decision and so is not a defect. It may be worth revisiting for the next standard.