How to implement swap()?

user541686 picture user541686 · Jul 24, 2012 · Viewed 10.8k times · Source

Possible Duplicate:
how to provide a swap function for my class?

Every time I think I understand it, I see something that really confuses me.

If you want to provide an implementation of swap for your own class, what do you do?

The list of possibilities is:

  1. Define one inside the std namespace (taking two arguments), which calls #3 below
    (some say this is correct; some people say illegal)

  2. Define a static method inside the class, taking two arguments to swap
    (makes more sense to me than #4, but I don't get why no one does this), which calls any base-class swaps as necessary

  3. Define an instance method inside the class, taking one other argument to swap with, which calls any base-class swaps as necessary

  4. Define an instance method inside the class, taking two other arguments to swap, also here, which calls any base-class swaps as necessary

  5. Define one in your own namespace (taking two arguments), which calls #3

  6. Something else

My own understanding is that I need #5 and #3, where the caller would then be calling swap likeusing std::swap; swap(a, b);,but the fact that no one seems to suggest that combination is really confusing me. And I really don't understand #4 at all, because everyone seems to be using an instance member when in fact the operation is static. I can't tell if my understanding is wrong or a bunch of the answers I see when looking this up.

What's the correct way?

Answer

David Rodríguez - dribeas picture David Rodríguez - dribeas · Jul 24, 2012

A common pattern I have seen is providing 3 and 5, as per your own understanding.

  1. adds an specialization to the std:: namespace, which is allowed, but might not be possible in all cases (if your type is a template itself).
  2. offers no advantage at all, and forces qualifying with the type when used outside of one of the members, which means that for implementing swap on other types that hold your type as a member, they will need to qualify the call (void swap( other& l, other& r ) { T::swap( l.t, r.t ); })
  3. does not need friendship, allows for use with rvalues (even in C++03) and is idiomatic in some cases std::vector<int>().swap( v ); to clear the contents of the vector.
  4. What? You misunderstood the code! That is not declaring a member taking two arguments, but rather a free function taking the two arguments, and defines the function inline. This is equivalent to 5 (without forwarding to 3, but rather implementing everything in the free function).
  5. Free function in the same namespace allows for ADL to find it, and enables other code to use the common pattern of void swap( other& l, other& r ) { using std::swap; swap( l.t, r.t ); } without having to know whether the type of other::t has an specific swap overload or the one in std:: needs to be used. Forwarding to 3 allows you to provide a single (real) implementation that can be used through ADL and also on temporary objects.