Какая часть спецификации C++ ограничивает зависимый поиск аргумента в нахождении шаблонов функций в наборе связанных пространств имен? Другими словами, почему делает последнюю возможность в main
ниже сбоя для компиляции?
namespace ns {
struct foo {};
template<int i> void frob(foo const&) {}
void non_template(foo const&) {}
}
int main() {
ns::foo f;
non_template(f); // This is fine.
frob<0>(f); // This is not.
}
В этой части объясняется это:
Стандарт C ++ 03 14.8.1.6 :
[Примечание: для простых имен функций поиск в зависимости от аргументов (3.4.2) применяется, даже если имя функции не отображается в рамках вызова. Это потому, что вызов по-прежнему имеет синтаксическую форму вызова функции (3.4.1). Но когда используется шаблон функции с явными аргументами шаблона, вызов не имеет правильной синтаксической формы, если не существует шаблона функции с таким именем, видимого в точке вызова. Если такое имя не отображается, вызов не имеет синтаксической правильной формы и поиск, зависящий от аргументов, не применяется. Если такое имя видно, применяется поиск, зависящий от аргументов, и дополнительные шаблоны функций могут быть найдены в других пространствах имен.
namespace A {
struct B { };
template<int X> void f(B);
}
namespace C {
template<class T> void f(T t);
}
void g(A::B b) {
f<3>(b); //ill-formed: not a function call
A::f<3>(b); //well-formed
C::f<3>(b); //ill-formed; argument dependent lookup
// applies only to unqualified names
using C::f;
f<3>(b); //well-formed because C::f is visible; then
// A::f is found by argument dependent lookup
}
Редактировать: Нет, это неправильно. См. @ Ответ Корнеля .
Я не совсем уверен, но, посоветовавшись с Страуструпом «Язык программирования C ++», я думаю, что причиной могло быть приложение C, раздел 13.8.4 .
Поскольку frob
является шаблоном, его можно было бы специализировать для i = 0
в момент после его вызова. Это означает, что реализации останется два возможных способа выбора того, какой frob
вызывать, поскольку он, по-видимому, может выбрать его в точке создания экземпляра или в конце обработки перевода. Ед. изм.
Итак, я думаю, проблема в том, что вы могли бы сделать
namespace ns {
struct foo {};
template<int i> void frob(foo const&) {}
}
int main() {
ns::foo f;
frob<0>(f);
return 0;
}
namespace ns {
template<> void frob< 0 >(foo const&) { /* Do something different*/ }
}