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;
}
The output is (ideone link):
int
This makes sense to me: foo(what<true>&, const int&) matches the const_cast overload, which then calls foo(what<true>&, int&), which matches the int overload.
Yet if I change 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));
}
The output is now (ideone link):
generic
This doesn't make sense to me. Why does changing that const_cast overload of foo to call ::foo cause the generic version to get called instead of the int version?
My understanding of :: is that it was just to disambiguate which function to call in the case you have a method or a function in the global namespace. The const_cast overload still matches, which should then call ::foo(what<true>&, int&), which should match the int specialization - shouldn't it?
Further, if I change the order and place the const_cast overload using ::foo after the int specialization, then the int specialization gets called (ideone link). Why does the order of definition matter here?
Names declared after the template can only be found via argument-dependent name lookup. Your overload of foo for int& is only found because one of the types involved, W<true>, is a specialization of a class template declared in the global namespace. Hence ADL looks for declarations in the global namespace in the instantiation context and finds the (more specialized), desired overload.
::foo is a qualified-id, which suppresses ADL, hence only names declared in the definition context are considered.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With