Почему ADL не находит шаблоны функций?

Какая часть спецификации 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.
}
79
задан curiousguy 28 July 2018 в 13:20
поделиться

2 ответа

В этой части объясняется это:

Стандарт 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
}
82
ответ дан 24 November 2019 в 10:19
поделиться

Редактировать: Нет, это неправильно. См. @ Ответ Корнеля .


Я не совсем уверен, но, посоветовавшись с Страуструпом «Язык программирования 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*/ }
}
0
ответ дан 24 November 2019 в 10:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: