Why is using the scope resolution operator change caused by an overloaded template in the global namespace?

Consider the following code:

#include <iostream> template <class W, class T> void foo(W& a, T& t) { std::cout << "generic" << std::endl; } template <template <bool> class W, class T> void foo(W<true>& a, const T& t) { foo(a, const_cast<T&>(t)); } template <class W> void foo(W& a, int& t) { std::cout << "int" << std::endl; } template <bool> struct what; template<> struct what<true> { }; int main() { const int ci = 10; what<true> wt; foo(wt, ci); return 0; } 

Output signal ( ideone link ):

 int 

This makes sense to me: foo(what<true>&, const int&) corresponds to a const_cast overload, which then calls foo(what<true>&, int&) , which corresponds to an int overload.

But if I changed the const_cast function to the following:

 template <template <bool> class W, class T> void foo(W<true>& a, const T& t) { ::foo(a, const_cast<T&>(t)); } 

Now output ( ideone link ):

 generic 

That doesn't make sense to me. Why const_cast changing this const_cast overload of foo to a call ::foo cause the generic version to receive the call instead of the int version?

My understanding :: is that you just need to eliminate which function to call if you have a method or function in the global namespace. The overload of const_cast is still the same, which then should call ::foo(what<true>&, int&) , which should match the int specialization - isn't it?

Also, if I change the order and put the const_cast overload using ::foo after the int specialization, then the int ( ideone link ) specialization will be called. Why is the order of definition defined here?

+7
c ++ templates overload-resolution template-specialization
source share
1 answer

Names declared after a pattern can only be found through argument-dependent name lookups . Your foo overload for int& only found because one of the types, W<true> , is a specialization of the class template declared in the global namespace. Consequently, the ADL looks for declarations in the global namespace in the context of the instance and finds the (more specialized) desired overload.

::foo is a qualified identifier that suppresses ADL, so only names declared in the definition context are considered.

+4
source share

All Articles