H
Howard Hinnant
[/QUOTE]In the "splice some from other" case, the splice function must compute:
std::distance(first, last);
where [first, last) represents the range "some" which is to be spliced
from other. So the constant on that linear complexity term is really
quite small (but of course not zero).
I think there is an additional case here: if the source and
destination lists have different allocators, the items actually
have to be copied and the 'splice some/all from other' is O(N) anyway
- so there is no cost in counting them to maintain an O(1) list size.
<nod> I intentionally ignored the unequal allocators case. I do discuss
this in a little more detail here:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1599.html
This paper is about swap for containers of unequal allocators, but
splice is a closely related issue.
I feel that turning splice (and swap) into an element by element copy is
too dangerous because it silently turns a nothrow operation into a
throwing operation. This could silently invalidate client code which
has been crafted with a nothrow splice/swap in mind. If this situation
occurs, I'd prefer it be as noisy as possible the very first time it
gets executed instead of silently trying to please.
In addition to the changed exception guarantees, iterator validity also
would get silently messed up with an element-by-element copy (see below).
Since we are talking about splice, I dare ask another question:
I am currently using splice(1 item from self) to move items within
an std::list. The standard seems to say that iterators to moved
items are always invalidated by splice. But in the case where the
source and destination lists are the same, I see no practical reason
for the iterator to be invalidated (and all the implementations of
std::list I reviewed seem to agree). And I am using std::list just
for that reason: to be able to keep iterators to specific items.
But this does not seem to be guaranteed by the standard (ISO '98).
Is this a reasonable omission?
Is there a safe way to move items in an std::list without
invalidating iterators?
[NB: I asked similar questions in clc++m, with no enlightening reply
yet: "std::list::splice to move item within the same list[...]" ]
This is a defect in the standard, and has a proposed resolution with WP
status. WP status means that the committee has voted on the proposed
resolution and is happy with it, and has applied it to the working paper
for C++0X.
http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#250
The proposed resolution does what you believe is reasonable, and find in
practice. Although I did not initiate this issue, by coincidence, I did
write the current proposed wording.
Also, am I right to believe that list::sort preserves iterators?
Yes. Reference 23.1p11:
Unless otherwise specified (either explicitly or by defining a function in
terms of other functions), invoking a container member function or passing a
container as an argument to a library function shall not invalidate iterators
to, or change the values of, objects within that container.
Thank you Howard.
Kudos for your excellent work, I keep fond memories of the early days
of CW on the Mac, which was the first C++ lib I used (and enjoyed!).
Thanks for your kind words.
-Howard