Iter_Swap() Versus Swap() -- What's the Difference

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 that swap(*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 of std::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 interpret swap(*a, *b).

All of these seem to suggest that it is an artifact of the past.

What's the point of iter_swap?

From the SGI docs (here):

[1] 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 interpret swap(*a, *b).

std::iter_swap requires ValueSwappable args vs std::swap requires Move Assignable args

The swap called inside iter_swap is not fully qualified i.e not called as std::swap but just as swap. Therefore, during name lookup and ADL compiler finds multiple functions which matches with the call to swap. But, the overload resolution selects the swap provided by you since it matches best.

If you use swap in your main code, then it would compile fine as it would not find std::swap. It will compile even if you do using namespace std;

Why/when should we prefer using std::swap; swap(a, b) over std::iter_swap(&a, &b)?

3 years later, but I believe the only technical concern would be if operator &() is overloaded.

If not, the only other reason I see would be readability.

Is this way of swapping 2 numbers better or worse than the one that uses a temp variable?

You should say what language you are using first of all.

In general I think its safe to say that "in-place swap" is preferable, from a performance standpoint, to swapping using a temporary.

In C or C++ the above is not good because if you cause integer overflow you get undefined behavior.

In those languages it's better to use bitwise operations for this. The basic observation is that if A and B are bits and we use addition modulo 2, then this is a swap (pseudocode):

a += b;
b += a;
a += b;
// Now A and B are swapped if they are numbers mod 2.

In C / C++ you would therefore use bitwise XOR in the above pattern, to do it to all of the corresponding bits at once.

I believe that's how e.g. the standard swap implementation for two pointers is implemented. (OTOH it's possible that this could just happen as a compiler optimization)

It has the benefit that the in-place version can't fail, while the version that uses a temporary variable can potentially blow the stack if the objects being swapped are too large.

The XOR swap is also substantially better than the naive swap implementation if a and b are smart pointer types -- creating a temporary smart pointer could cause allocations, call a user defined constructor, have side effects, and potentially throw exceptions, meaning that the swap is no longer a no-fail, noexcept function. The XOR swap avoids all of that.

Incremented iterator std::next when swapping

In the first code, the order of evaluation of the two ops *i and *(++i) unspecified after c++17, hence the second one may execute before the first, and then the swapping swaps two equivalent values.

In the attached link, u can see that

f(++i, ++i); // undefined behavior until C++17, unspecified after C++17

But in the second code you have different parameters and std::next() returns a new iterator.



Related Topics



Leave a reply



Submit