Отклонение типа шаблона Variadic приводит к сбою компиляторов, если есть замена на выводимый тип - PullRequest
0 голосов
/ 10 октября 2018

Мне кажется, что во всех компиляторах я обнаружил ошибку вывода типа шаблона, но перед тем, как сообщить об этом, я хочу убедиться, что ничего не пропустил.

Рассмотрим пример:

#include <utility>

template <std::size_t... I, typename... T>
void foo(std::index_sequence<I...>, decltype(I)..., T...) {}

int main()
{
    foo(std::make_index_sequence<3>{}, 1, 2, 3, 4, 5);
}

decltype(I) используется здесь для сокращения MWE.

  • GCC: error: too few arguments to function
  • Clang аварийно завершает работу с error: no matching function for call to 'foo'
  • MSVC падает с error C3543: 'unknown-type': does not contain a parameter pack

Я не понимаю, почему он не вычитает T, особенно потому, что он работает, если я заменяю пакет параметров на varargs (кроме MSVC,у него снова ЛЕД).

template <std::size_t... I>
void foo(std::index_sequence<I...>, decltype(I)..., ...) {}

Есть много других способов сделать то, что я хочу, но это самый короткий путь, и я не вижу причин, по которым он должен потерпеть неудачу.

Обновление : Известный действительный пример с подстановкой на deducible:

template <typename T>
struct type_identity
{ using type = T; };

template <typename T, typename... U>
void foo(T, typename type_identity<T>::type, U...) {}

int main()
{
    foo(1, 2, 3, 4, 5);
}

Обновление # 2 Модифицированная версия исходного примера не приводит к сбою Clang, но к сведениюпо ошибке странно note: candidate template ignored: deduced conflicting types for parameter 'T' (<int, int, int> vs. <>)

#include <utility>

template <typename T>
struct type_identity
{ using type = T; };

template <typename...>
struct type_pack {};

template <typename... T, typename... U>
void foo(type_pack<T...>, typename type_identity<T>::type..., U...) {}

int main()
{
    foo(type_pack<int, int, int>{}, 1, 2, 3, 4, 5);
}

1 Ответ

0 голосов
/ 10 октября 2018

Я думаю, что ваш код плохо сформирован стандартом, но можно привести аргумент, что стандарт должен быть изменен, чтобы сделать его правильно сформированным.

Процесс вывода аргумента шаблона описан в стандартеследующим образом:

  1. Явно указанные аргументы шаблона подставляются в объявление шаблона функции ( [temp.deduct] / 2-5).
  2. Остальные параметры шаблонакоторые выводятся в выведенных контекстах в списке параметров-типов, выводятся ( [temp.deduct.call] ).
  3. Выведенные аргументы шаблона вместе с параметрами шаблона, которые имеют аргументы шаблона по умолчанию, подставляются в объявление функции [temp.deduct.call] / 10 .Это конец процесса удержания, за которым следует разрешение по перегрузке.

Таким образом, процедура является substitution-deduction-substitution ;после замены выведенных аргументов последующий вывод не производится.Дальнейшая поддержка этого представления обеспечивается [temp.deduct] / 6 :

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

Ваш пример плохо сформирован, потому что он требует вычитания, затем подстановки, а затем вычета: T... не может быть выведено, если I... не является первым и не выводится, а подставляется .

...