7

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?

Claudiu
  • 224,032
  • 165
  • 485
  • 680

1 Answers1

4

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.

Columbo
  • 60,038
  • 8
  • 155
  • 203