7

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

There are some questions about this, but a lot of contradictions (person A giving solution A' with many upvotes with person B saying it's UB) or "only works if the compiler supports ADL" is answered.

So, say I have the following template (container) class:

template<typename T>
class C {
    // ...
    void swap(C<T>& y) throw(); // C x; x.swap(y);
}

then what is the correct way to make sure this (example) code works:

C<int> x, y;
std::swap(x, y);

Please give your answer for C++03, and if it still works in C++0x, even better!

Community
  • 1
  • 1
orlp
  • 112,504
  • 36
  • 218
  • 315
  • Xeo: That's about a non-template class. – orlp Jun 20 '11 at 16:17
  • @night: No, it counts for every class. – Xeo Jun 20 '11 at 16:18
  • Xeo: "3) Explicit specialization of std::swap." I don't see that happening with a template class. – orlp Jun 20 '11 at 16:19
  • @night: Yeah, since you can't partially specialize, what is left? Free function in your namespace, 2) in my answer. I amended it to explicitly state that now, though. – Xeo Jun 20 '11 at 16:20
  • Xeo: That depends on ADL, is there any other way? – orlp Jun 20 '11 at 16:21
  • @night: Yes, put it in global namespace, but... just do what everyone does and you'll be fine. Also, providing a namespace for your stuff is generally good. – Xeo Jun 20 '11 at 16:22
  • Generally, but this is a single concept with a single class in a single header. Is there any way to use this without using a namespace? Or `namespace C { /* ... */ } using namespace C;`? – orlp Jun 20 '11 at 16:25
  • That's the same as putting it directly in global namespace. :P – Xeo Jun 20 '11 at 16:28
  • But now ADL will find my swap... right? – orlp Jun 20 '11 at 16:29
  • Your swap will also be found without ADL if you put it directly in global namespace, I believe. Let me test that. **Edit**: Yes, it does. – Xeo Jun 20 '11 at 16:29

1 Answers1

7

You are not allowed to overload functions in the std-namespace.

Declare swap as a free function, overloaded in the same namespace as your class C:

 template<class T>
 void swap(C<T>& x, C<T>& y) { x.swap(y); }

The right way to swap is to import std::swap and use a non-qualified version (which is retreieved via namespace-based Koenig lookup):

 template<class T>
 void dostuff(T x, T y) {
    ...
    using std::swap;
    swap(x,y);
    ...
 }

That will use C::swap if x and are C, and std::swap for types that do not have their own swap.

(The import of std::swap like above is only necessary in template functions where the type is not known. If you know you have a C, then you can use x.swap(y) right away w/o problems.)

Macke
  • 24,812
  • 7
  • 82
  • 118
  • This forces me to put my `C` in a namespace. Or is a anonymous namespace sufficient? – orlp Jun 20 '11 at 16:18
  • @nightcracker: No, as every translation unit will now have your class in a different namespace, afaik. – Xeo Jun 20 '11 at 16:23
  • @nightcracker: You can have C in the global namespace if you like, or an anonymous namespace, if you only use C (and it's swap) in a single translation unit. The point is that C and it's free swap-function must be in the same one (i.e. don't put anything in the std namespace). – Macke Jun 20 '11 at 19:37