I have two snippets for ADL for demo purposes. Both fragments were compiled by VC10, gcc and comeau C ++ compilers, and the result is the same for all three.
<1> ADL versus using the user namespace directive:
#include <algorithm> namespace N { struct T {}; void swap(T,T) {} } namespace M { void swap(N::T,N::T) {} } int main() { using M::swap; N::T o1,o2; swap(o1,o2); }
Compilation result:
error C2668: 'M::swap' : ambiguous call to overloaded function could be 'void M::swap(N::T,N::T)' or 'void N::swap(N::T,N::T)' [found using argument-dependent lookup]
It is expected that ADL will not take precedence over a normal search result, and ADL is not a second-class citizen, the ADL search result is combined with a regular (non-ADL) unmanaged search. That is why we have ambiguity.
<2> ADL versus using the std namespace directive:
#include <algorithm> namespace N { struct T {}; void swap(T,T) {} //point 1 } namespace M { void swap(N::T,N::T) {} } int main() { using std::swap; N::T o1,o2; swap(o1,o2); }
This one compiles fine.
As a result, the compiler selects the ADL result (it has the precedent std :: swap), which means N::swap() at point 1. Only when in the paragraph “point 1” (say, if I comment on this line), the compiler instead this will use the std::swap rollback.
Note that this method has been used in many places as a way to overwrite std::swap . But my question is: why does ADL take precedence over "std namespace" (case2), but is considered equal to the user-defined namespace function (case1)?
Is there a paragraph in the C ++ standard that says that?
==================================================== ================================ Edit after reading useful answers may be useful to others.
So, I changed my fragment 1, and now the uncertainty has disappeared and compiled, if desired, when performing the overload, the resolution prefers the Nontemplate function!
#include <algorithm> namespace N { struct T {}; void swap(T,T) {} } namespace M { template<class T> void swap(N::T,N::T) {} } int main() { using M::swap; N::T o1,o2; swap(o1,o2); //here compiler choose N::swap() }
I also changed my fragment 2. Just to make the ambiguity appear just for fun!
#include <algorithm> namespace N { struct T {}; template<class _Ty> inline void swap(_Ty& _Left, _Ty& _Right) { _Ty _Tmp = _Move(_Left); _Left = _Move(_Right); _Right = _Move(_Tmp); } } namespace M { void swap(N::T,N::T) {} } int main() { using std::swap; N::T o1,o2; swap(o1,o2); }
gcc and come both talk about ambiguity as expected:
"std::swap" matches the argument list, the choices that match are: function template "void N::swap(_Ty &, _Ty &)" function template "void std::swap(_Tp &, _Tp &)"
BTW VC10 is stupid, as usual, let it go fine if I don't remove 'using std :: swap'.
A little more is written: C ++ overloading can be complicated (30+ pages in the C ++ standard), but appendlix B has a very readable 10-page page ...
Thanks for all the nice entries, now I see.