Законно ли опускать аргументы типа шаблона при создании экземпляра шаблона функции? - PullRequest
2 голосов
/ 09 марта 2020

Следующий код реализует шаблон функции foo, который принимает произвольное количество аргументов и впоследствии обрабатывает каждый из них, сохраняя позиционный индекс этого аргумента:

template<int index, typename T>
void foo_impl(T value)
{
    // Do something with index/value
}

template<int index, typename T, typename... Rest>
void foo_impl(T value, Rest... values)
{
    // Do something with index/value
    // Recursively handle remaining arguments
    foo_impl<index + 1>(values...);
}

template<typename... T>
void foo(T... args)
{
    foo_impl<1>(args...);
}

int main()
{
    foo("test", 42);
}

Это рекурсивно создает шаблоны функций до он достигает базового шаблона, который принимает один аргумент. В каждом экземпляре шаблона функции foo_impl пропущены аргументы типа шаблона. Хотя это компилируется с Clang, G CC и MSV C, я не уверен, что это допустимо.

Допустимо ли опускать аргументы шаблона, как показано в пример кода? Если да, то каковы конкретные правила c? И изменились ли эти правила между стандартами C ++?

1 Ответ

6 голосов
/ 09 марта 2020

Указанное правило c находится в [temp.arg.explicit]

3 Конечные аргументы шаблона, которые могут быть выведены или получены из Шаблонные аргументы по умолчанию могут быть опущены из списка явных аргументов шаблона. Конечный пакет параметров шаблона, не выведенный иначе, будет выведен в пустую последовательность аргументов шаблона. Если все аргументы шаблона могут быть выведены, все они могут быть опущены; в этом случае сам список пустых аргументов шаблона <> также может быть опущен. В тех случаях, когда дедукция выполняется и происходит сбой, или в тех случаях, когда дедукция не выполняется, если указан список аргументов шаблона, и он вместе с любыми аргументами шаблона по умолчанию идентифицирует специализацию одного шаблона функции, то идентификатор шаблона является lvalue для специализации шаблона функции.

Поскольку аргументы типа являются конечными и могут быть выведены из аргументов вызова функции, они могут быть опущены.

Такое многословие существует во всех стандартные версии на сегодняшний день (за исключением части о пакетах параметров, которой нет в C ++ 03).

...