3

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

Pradhan
  • 16,391
  • 3
  • 44
  • 59
user541686
  • 205,094
  • 128
  • 528
  • 886
  • @T.C.: lol, fair enough, but any other cases? (But feel free to post that as an answer...) – user541686 May 18 '15 at 00:12
  • 2
    I'd think you should almost always "prefer" it for the readability benefit – happydave May 18 '15 at 00:13
  • Can you actually put your question in your question, it's hard to parse that "using" is the keyword using, not the actual word – Barry May 18 '15 at 00:13
  • 1
    Also didn't you ask almost this question two years ago? http://stackoverflow.com/questions/14024228/iter-swap-versus-swap-whats-the-difference – Barry May 18 '15 at 00:14
  • @Barry: It's not the same question... it didn't occur to me that I might be able to use `iter_swap` instead of `swap` back then. And okay sure. – user541686 May 18 '15 at 00:15
  • @happydave: It's a fair answer, feel free to post it... – user541686 May 18 '15 at 00:26
  • 1
    @Mehrdad. Well, after I wrote the comment, I started having second thoughts. The extra using statement is non-obvious in itself, so my comment may just reflect the bias of my own experience. – happydave May 18 '15 at 00:30

4 Answers4

0

Since they are completely different your question is a false dichotomy.

They do different things!

  • One swaps value.
  • The other swaps the content of the destination of iterator.

But if you have iterators. It is probably better to use std::iter_swap. Otherwise you can use swap (as long as you have done the using std::swap; locally to the call to swap (otherwise the type dependent lockup for the correct swap may fail).

std::iter_swap(i1, i2);

// Is equivelent to writing.
using std::swap;  // Notice this. 
swap(*i1 ,*i2);   // Notice the * in front of the iterator.
Barry
  • 286,269
  • 29
  • 621
  • 977
Martin York
  • 257,169
  • 86
  • 333
  • 562
  • Nope, they cannot do different things as far as I can tell (barring an overloaded `&`); the standard mandates that the latter must have the same effects as the former. – user541686 May 18 '15 at 00:16
  • @Mehrdad: They definitely do completely different things. – Martin York May 18 '15 at 00:18
  • Can you give an example of when the type dependent lookup can fail? And no, they can't do different things... can you give an example of when they do different things? – user541686 May 18 '15 at 00:18
  • @Mehrdad: Read my answer. One deference the iterator the other does not. How much more different do you want. – Martin York May 18 '15 at 00:20
  • Are you sure you read my question carefully? The code in your answer is not the same as the one I asked about. – user541686 May 18 '15 at 00:21
0

Generally, the standard mandates that

std::iter_swap(&a, &b);

has the an effect equivalent to

using std::swap;
swap(*(&a), *(&b));

whereas it may be implemented differently. (at least g++ and msvc just swap...)

Knowing that, I'd consider

using std::swap;
swap(a, b);

to be more specific, direct and readable as it expresses the desired, adl-enabled behaviour directly.

If you have iterators in the first place, then I'd stick to ADL-enabled iter_swap:

using std::iter_swap;
iter_swap(it_a, it_b);

The reason here would be that I get two chances of outperforming (or outsmarting) default std::swap:

  1. The implementor of the container the iterators came from may have provided an overload for iter_swap for those iterators, which is smarter (and possibly even more appropriate1) than a plain value swap.
  2. The implementor of the class refered to by the iterator may have provided the swap overload to efficiently swap both elements.

If (1) is not the case I may get (2) and only if both options do not apply std::swap is used and moves (or in case of a non-moveable type copies) the objects around to swap them.

Note that std-algorithms using iter_swap do not adl-enable the call.

1 May apply to special iterator (ranges) which do not directly represent objects (i.e. zip-ranges).

Pixelchemist
  • 24,090
  • 7
  • 47
  • 71
  • There is no practically useful way to achieve the effect of `swap` without actually calling `swap`... that's why it ended up being redundant and unused. – user541686 Oct 25 '16 at 03:31
  • @Mehrdad: Actually we're missing something like `iter_move` as well to make `iter_swap` a really useful customization point but it could well be used that way. – Pixelchemist Oct 25 '16 at 04:35
0

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.

user541686
  • 205,094
  • 128
  • 528
  • 886
-1

From http://en.cppreference.com/w/cpp/algorithm/iter_swap

Possible implementation

template<class ForwardIt1, class ForwardIt2>
void iter_swap(ForwardIt1 a, ForwardIt2 b)
{
   using std::swap;
   swap(*a, *b);
}

Given that, I think

using std::swap;
swap(a,b);

is better than

using std::iter_swap;
iter_swap(&a, &b);

The first one involves less typing and more to the point.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • Wrong for any specific use case(s)? – R Sahu May 18 '15 at 00:15
  • You need to use argument-dependent lookup, otherwise it won't look up any user-defined `swap` via ADL. – user541686 May 18 '15 at 00:16
  • @Mehrdad, I need to dig deeper into that. It's not obvious to me. – R Sahu May 18 '15 at 00:19
  • @Barry: `std::swap(a,b);` is most definitely *not* using ADL. (Are you looking at the right thing?) – user541686 May 18 '15 at 00:20
  • @Barry: No! Did you read the actual *answer*? It says *"Given that, I would think `std::swap(a,b);` seems better than `std::iter_swap(&a, &b);`"* The first one and the second one are not equivalent. – user541686 May 18 '15 at 00:22
  • 1
    @R Sahu: Yeah, it's not very obvious, but `using std::swap; swap(a, b);` is not equivalent to `std::swap(a, b);`. – user541686 May 18 '15 at 00:29
  • @Mehrdad, that definitely surprises me. If you can point to something for further reading, I'd appreciate it. – R Sahu May 18 '15 at 00:34