Вопрос

Какая часть спецификации 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
}

Другие советы

Я хотел бы уточнить слегка принятый ответ. Это не ясно в вопросе OP, но важной частью стандарта (цитируемой Kornel) является это (акцент на моем):

Но когда шаблон функции с явные аргументы шаблона используется, вызов не имеет правильной синтаксической формы

Итак, что запрещено, так это полагается на ADL и использование явных аргументов шаблонов. К сожалению, использование аргументов шаблонов, не являющихся типом, требует использования явных аргументов (если у них нет значений по умолчанию).

Ниже приведен пример кода, показывающий это.:

жить

#include <string>
#include <utility>

namespace C {
  struct B { };
  template<class T> void f(T t){}
}

void g(C::B b) {
  f(b);           // OK
  //f<C::B>(b);   // ill-formed: not a function call, but only 
                  //  because explicit template argument were used

  std::string s;
  move(s);                      // OK
  //move<std::string&>(s);      // Error, again because 
                                //  explicit template argument were used
  std::move<std::string&>(s);   // Ok
}

int main()
{
 C::B b;
 g(b);
}

Поскольку C ++ 20, ADL работает также хорошо с явным шаблоном функций. Вот предложение:P0846R0: шаблоны ADL и функции, которые не видны:

Вместо того, чтобы потребовать, чтобы пользователь использовал ключевое слово Template, была предложена пересмотр правил поиска, так что имя, для которого нормальный поиск не дает либо никакого результата, либо находит одну или несколько функций и за которым следует AA "<" Если бы было найдено имя шаблона функции и приведет к выполнению ADL.

В настоящее время только GCC 9 реализует эту функцию, поэтому ваш пример может составить.

live demo.

РЕДАКТИРОВАТЬ: Нет, это не правильно. Видеть @Ответ Корнеля.


Я не совсем уверен, но проконсультировался с «языком программирования C ++». мощь быть причиной.

С 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*/ }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top