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?