Вычет конечного аргумента шаблона в объявлении явных специализаций шаблонов функций (без функции аргумент вычета) - PullRequest
4 голосов
/ 23 апреля 2020

(Этот вопрос является ответом на обсуждение в комментариях Шаблонная специализация шаблона переменной и вычитание типа .)


[temp.expl.spec] / 10 утверждает, что [ emphasis mine]:

Завершающий аргумент шаблона можно не указывать в template-id , указав явную специализацию шаблона функции , при условии, что она может быть выведена из типа аргумента функции . [Пример:

template<class T> class Array { /* ... */ };
template<class T> void sort(Array<T>& v);

// explicit specialization for sort(Array<int>&)
// with deduced template-argument of type int
template<> void sort(Array<int>&);

- конец примера]

Что явно относится к (полной) явной специализации foo(T) в следующем примере:

#include <iostream>

template <typename T>
void foo(T) { std::cout << "primary\n"; }

template <>
void foo(int) { std::cout << "int\n"; }
// OK   ^<int> deduced from template argument deduction
//             in this _declaration_, as of [temp.expl.spec]/10

int main()
{
    const int a = 42;
    foo(a);  // int
    // OK, <int> deduced from template argument deduction.
}

Однако и для clang, и для G CC, для всех различных версий ISO C ++, которые я тестировал, это также применимо в примере, где нет аргументов функции в шаблоне функции, и где ее, скажем, шаблон типа Параметр присутствует только в качестве типа возврата шаблона функции:

#include <iostream>

template <typename T>
T bar() { std::cout << "primary\n"; return 0; }

template <>
int bar() { std::cout << "int\n"; return 42; }
//     ^<int> deduced?

int main()
{
    (void)bar<int>();  // int
    //        ^^^ OK, no template argument deduction.
}

Я немного запутался с термином "deduced" в приведенной выше цитате, поскольку он, как говорится, не относится к выводу в смысле типичного (вызов сайта / создания экземпляра) вывода аргумента шаблона, а скорее к выводу в контексте объявления специализации.

Вопрос:

  • Где это охватывается в стандарте ISO C ++, что конечный аргумент шаблона в объявлении явной специализации шаблона функции с аргументом шаблона присутствует только в качестве рету Тип rn, может быть фактически опущен (выведен)?

1 Ответ

3 голосов
/ 23 апреля 2020

Я думаю, что [temp.expl.spec] / 10 имеет неверную формулировку, говоря «тип аргумента функции» вместо просто «тип функции», что фактически используется для вывода аргумента шаблона для явной специализации шаблона функции , (Плюс, конечно, может быть более одного типа аргумента функции.)

Различные контексты определяют разные наборы зависимых типов (P) и определенных (часто независимых) типов (A) для использоваться при выводе аргументов шаблона, как указано в подразделах [temp.deduct.call] , [temp.deduct.funcaddr] , [temp.deduct.conv] , [temp.deduct.partial] и [temp.deduct.decl] .

Наиболее знакомый случай, вероятно, является первым из них, [temp.deduct.call] : при вызове шаблона функции типы параметров функции равны P, а типы выражений аргументов A, но тип возвращаемого значения шаблона функции не участвует .

Последний из них, [temp.deduct.decl] , охватывает сопоставление для явных специализаций шаблона функции (как в ваших примерах), явные экземпляры шаблона функции и объявления друзей, которые дружат с конкретным c specia список функциональных шаблонов. Для этих случаев целыми типами функций являются P и A. Поскольку тип функции считается «составным типом», сформированным из возвращаемого типа и типов аргументов, аналогично тому, как тип указателя T* формируется из типа T, это позволяет вывести параметры шаблона, появляющиеся в возвращаемом типе, и / или в типах аргументов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...