iter_swap() versus swap() -- what's the difference?
The standard itself has very few mentions of iter_swap
:
- It should have the effect of
swap(*a, *b)
, although there is no stipulation that it must be implemented that way. - The dereferenced values
*a
and*b
must be "swappable", which implies thatswap(*a, *b)
must be valid, and thus the dereferenced types must be identical, although the iterator types do not have to be. iter_swap
is required to be used in the implementation ofstd::reverse
. No such requirement is placed on any other algorithm, so this seems to be an oddity.
To borrow what sehe had found from the SGI docs:
Strictly speaking,
iter_swap
is redundant. It exists only for technical reasons: in some circumstances, some compilers have difficulty performing the type deduction required to interpretswap(*a, *b)
.
All of these seem to suggest that it is an artifact of the past.
This seems to be one of those scenarios in which the internet produces a host of conflicting information.
cplusplus.com says that
iter_swap
is identical toswap
and, by that logic, MSDN would be correct in saying that one ought to simply stick toswap
.cppreference.com tells us that calling
swap
is merely a possible implementation foriter_swap
, opening the door for possible optimisations initer_swap
for certain specialisations, as long as the function's constant complexity guarantee is upheld.
The standard, under [C++11: 25.3.3/5]
, says only that iter_swap(a,b)
has the result swap(*a,*b)
(and requires that "a
and b
shall be dereferenceable", and that "*a
shall be swappable with *b
") which would at first glance correlate with MSDN's interpretation.
However, I believe Microsoft have neglected to consider the as-if rule, which should allow an implementation to make iter_swap
faster than swap
in certain cases (e.g. elements of a linked list).
I would therefore trust that the comp.std.c++
quote is the more technically accurate of the two.
That being said, there is a fairly strict limit on the optimisation that may be performed. Consider, for example, an implementation of iter_swap
over linked list elements that simply re-links nodes rather than physically swapping the element values — this is not a valid implementation, because the requirement that iter_swap
's observable behaviour match swap
's is violated.
I would therefore suggest that in practice there can be little if any benefit to preferring iter_swap
over swap
, and I'd recommend sticking to the latter for simplicity and consistency. C++11 move semantics ought to make swap
a cinch in many cases anyway.
Yes, they both do the same thing, when used properly. No, std::iter_swap
is not deprecated (by being placed in the Standard's §D Compatibility features section). MSDN's quote is misleadingly dismissive. The issue is that it's inconvenient to use std::swap
properly.
You should use iter_swap
for the simple reason that it's a higher abstraction.
swap
is commonly overloaded for user-defined types. The proper way to call it is
using std::swap;
swap( blah, bleh );
not simply
std::swap( blah, bleh );
This is ensconced in §17.6.3.2, in particular ¶3:
The context in which
swap(t, u)
andswap(u, t)
are evaluated shall ensure that a binary non-member function named “swap” is selected via overload resolution (13.3) on a candidate set that includes:— the two
swap
function templates defined in<utility>
(20.2) and— the lookup set produced by argument-dependent lookup (3.4.2).
iter_swap
is not such a special overloaded name, and customizing its functionality requires adding a template specialization to namespace std {}
.
Therefore, iter_swap
usefully encapsulates the part of the Swappable interface which you would otherwise implement every time.
It is actually a more friendly interface, regardless of whether there's ever a semantic difference for your implementation and its particular arguments. (Not that potential optimizations of it should be overlooked. MSDN may give their opinion, but they can't anticipate what library authors might provide using "backwards compatibility interfaces.")
As for a specialization of iter_swap
with an observably different result from swap( *a, *b )
, that would seem to be nonconformant with the requirement §25.3.3/5,
Effects:
swap(*a, *b)
.
The example you cite does sound like an observable difference, since pointers to *a
and *b
are both valid before and after the operation. That's unfortunately a bug in the library implementation.