Почему этот код C++, связанный с перегрузкой/пространством имен и шаблоном, не компилируется?

Вот некоторый код C++:

namespace A {

int f(int x) { return 0; }
int f(long x) { return 1; }

template<class T> int g(T x) {
  return f(x);
}

}

namespace B {
struct C {};
}

namespace A {
int f(B::C x) { return 2; }
}

void h() {
  A::g(B::C());
}

В пространстве имен A код объявляет несколько перегрузок функции f и шаблонной функции g, которая вызывает f. Затем мы объявляем новый тип в пространстве имен B и перегружаем f для нового типа в пространстве имен A. Компиляция с помощью g++ 4.2 дает

order.cpp: In function ‘int A::g(T) [with T = B::C]’:
order.cpp:21:   instantiated from here
order.cpp:7: error: no matching function for call to ‘f(B::C&)’
order.cpp:3: note: candidates are: int A::f(int)
order.cpp:4: note:                 int A::f(long int)

Код работает, если я делаю что-либо из следующего:

  1. Удалите пространства имен.
  2. Переместите перегрузку f для B::C в пространство имен B (благодаря поиску Koenig).
  3. Переместите объявление B::C и его перегрузку f над определением g().

Меня особенно озадачивает (3), так как у меня сложилось впечатление, что разрешение перегрузки должно быть независимым от порядка деклараций. Является ли это ожидаемым поведением C++?

12
задан Geoffrey Irving 2 December 2011 в 22:59
поделиться