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