   [C++] swap
  When I overload swap for my own types, should I do that in the std namespace?Or should I never call std::swap explicitly but rely on Koenig-lookup instead?   
  Google says to put it in namespace std.http://stackoverflow.com/questions/11562/how-to-overload-stdswap   ;  That website is wrong.swap, like other customization points, is supposed to be picked up by ADL (Koenig lookup). So you should overload it in the namespace your type is in.You might want to invoke it using boost::swap, which is implemented asnamespace boost{    template<typename T1, typename T2>    void swap(T1& t1, T2& t2)    {   using std::swap;   swap(t1, t2);    }}[Edited by - loufoque on August 29, 2009 3:23:03 PM];Quote:Original post by loufoqueswap, like other customization points, is supposed to be picked up by ADL (Koenig lookup).Even when I explicitly invoke std::swap? Just tested it, and the answer is no. So the solution seems to be this:namespace std{    template<>    void swap(String& a, String& b)    {   std::cout << "I'm in your swap!" << std::endl;    }};  No, you shouldn't invoke std::swap, this obviously doesn't perform ADL.Don't worry, your STL implementation performs ADL as well, since the call to swap won't be qualified.If you don't want to follow the standard guidelines and do silly things by putting your overload or specialzation in the std namespace, that's up to you. But ADL is the way for these things to work, just like operator overloading or begin/end for C++0x ranges.   ;Quote:Original post by loufoqueIf you [...] do silly things by putting your [...] specialization in the std namespace, that's up to you.But Scott Meyers recommends exactly that (Effective C++ Item 25).He also recommends what you mentioned about using and the unqualified swap.   ;  Eventually, what you want is that your swap overload would be picked up by the STL alglyorithms. Unfortunately there are "broken" implementations out there, e.g VC++ 2005's iter_swap:// TEMPLATE FUNCTION iter_swaptemplate<class _FwdIt1,class _FwdIt2> inlinevoid iter_swap(_FwdIt1 _Left, _FwdIt2 _Right){// swap *_Left and *_Rightstd::swap(*_Left, *_Right);}MinGW 3.4.5's implementation of iter_swap is even more broken, as it doesn't even attempt to call swap (and iter_swap is used everywhere in the algorithms, instead of swap):  template<typename _ForwardIterator1, typename _ForwardIterator2>    inline void    iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b)    { typedef typename iterator_traits<_ForwardIterator1>::value_type    _ValueType1; typedef typename iterator_traits<_ForwardIterator2>::value_type    _ValueType2; // concept requirements __glibcxx_function_requires(_Mutable_ForwardIteratorConcept<   _ForwardIterator1>) __glibcxx_function_requires(_Mutable_ForwardIteratorConcept<   _ForwardIterator2>) __glibcxx_function_requires(_ConvertibleConcept<_ValueType1,   _ValueType2>) __glibcxx_function_requires(_ConvertibleConcept<_ValueType2,   _ValueType1>) const _ValueType1 __tmp = *__a; *__a = *__b; *__b = __tmp;    }This appears to be fixed in 4.4.1:  template<>    struct __iter_swap<true>    { template<typename _ForwardIterator1, typename _ForwardIterator2>   static void    iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b)   {swap(*__a, *__b);   }    };;Quote:Original post by visitorEventually, what you want is that your swap overload would be picked up by the STL algorithms.That's exactly what I want, yes.   ;The wikipedia page on ADL, on top of explaining what ADL is, also shows how to use it with swap.Quote:Unfortunately there are "broken" implementations out there, e.g VC++ 2005's iter_swap:Interfacing with broken implementations is out of the scope of good C++ practices IMHO.(MSVC9 appears to have fixed it, by the way)   ;Quote:Original post by loufoqueThat website is wrong.Why?  What does relying on ADL gain you?  I can see what it loses you:  performance when someone fucks up and calls the qualified std::swap directly -- a very easy 'mistake' to make.  More importantly, a mistake you should expect your coworker to make.  And your standard library writer, apparently.  Why is the trivial task of making swap a specialization in the std namespace to avoid this being an issue "silly"?   