Ответ 1
Clang дает следующее сообщение об ошибке, которое дает некоторые подсказки:
$ clang -fsyntax-only test.cc -Wall
test.cc:7:10: error: call to function 'f' that is neither visible in the
template definition nor found by argument-dependent lookup
return f(x);
^
test.cc:21:3: note: in instantiation of function template specialization
'A::g<B::C>' requested here
A::g(B::C());
^
test.cc:17:5: note: 'f' should be declared prior to the call site or in
namespace 'B'
int f(B::C x) { return 2; }
^
1 error generated.
В частности, вы столкнулись с детальностью двухфазного поиска зависимых имен в определениях шаблонов. В С++ 98 [temp.dep.candidate] говорит:
Для вызова функции, который зависит от параметра шаблона, если имя функции является неквалифицированным идентификатором, но не идентификатором шаблона, функции-кандидаты определяются с использованием обычных правил поиска (3.4.1, 3.4.2), за исключением что:
- Для части поиска, использующей поиск неквалифицированного имени (3.4.1), найдены только объявления функций с внешней связью из контекста определения шаблона.
- Для части поиска с использованием связанных пространств имен (3.4.2) найдены только объявления функций с внешней связью, найденные либо в контексте определения шаблона, либо в контексте создания шаблона.
Так как A::f(B::C x)
не найден с использованием связанных пространств имен (например, зависящий от аргументов поиск), он должен быть видимым на сайте определения шаблона, а не только в момент создания экземпляра.