Разрешение перегрузки шаблона функции с двумя пакетами параметров - PullRequest
0 голосов
/ 18 ноября 2018

Рассмотрим следующий код:

#include<iostream>

template<class..., class... T>
int f(T...) { return 1; }

template<class... T>
int f(T...) { return 2; }

int main()
{
    std::cout << f(1);
}

Он компилирует и печатает 1 на gcc 8.2, но не может скомпилировать на clang 7 из-за неоднозначности вызова f(1).

Если вызов заменен на f(), оба компилятора не могут скомпилировать, утверждая, что вызов является неоднозначным.

Если пакеты параметров class... T заменены простым параметром class TT... с T), оба компилятора также заявляют о неоднозначности.

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

Редактировать:

Насколько я понимаю, чтодвойной пакет сам по себе не является неправильным, потому что [temp.param] 17.1 / 15 в моем чтении явно разрешает это, если второй пакет выводится из аргументов функции, что, по-видимому, имеет место из-за T...Пакет параметров функции.

Можно также явно указать аргументы первого пакета параметров, но не вторые, и поэтому не всегда (после вычета аргументов шаблона) хотя бы один пакет параметров пуст,Я не уверен, делает ли это программу плохо сформированной, потому что я не знаю, как читать, например, [temp.res] 17.7 / 8.3 в этом контексте.

Как gcc, так и clang кажутся хорошими ссам пакет двойных параметров, например, когда устранена перегрузка второго шаблона функции, оба компилятора печатают 1.Но это может быть случай плохо сформированный, диагностика не требуется .

Кроме того, я предполагаю, что с выводом аргумента шаблона класса шаблон класса variadic может иметь определенный шаблон конструктора variadic, которыйподразумевает кандидата-конструктора, похожего на мой пример пакета с двумя параметрами, и, насколько я понимаю, в этом контексте имеет место одно и то же разрешение перегрузки и вывод аргумента шаблона.Этот вопрос был мотивирован другим вопросом с такой настройкой: Сбой вывода шаблона класса Variadic с gcc 8.2, компилируется с помощью clang и msvc См. Также обсуждение по следующим темам: Руководства по дедукции и шаблоны класса variadic сконструкторы шаблонов переменных - несоответствующие длины пакета аргументов

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

1 Ответ

0 голосов
/ 18 ноября 2018

Здесь есть две проблемы.


Во-первых, [temp.deduct.partial] / 12 (я также цитирую пример, так как он похож на ваш), говорит:

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

template <class T> T f(int);            // #1
template <class T, class U> T f(U);     // #2
void g() {
  f<int>(1);                            // calls #1
}

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

Типы, используемые для частичного упорядочения, T... согласно [temp.deduct.частичное] / 3 :

Типы, используемые для определения порядка, зависят от контекста, в котором выполняется частичное упорядочение:

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

  • ...

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

Это может быть связано с ошибкой 49505 GCC.


Во-вторых, даже если второй шаблон функции не существует,колл все равно должен быть плохо сформирован.Согласно [temp.arg.explicit] / 3 :

... Пакет параметров шаблона trailing , не выведенный иным образом, будет выведен в пустойпоследовательность аргументов шаблона ...

Только конечный пакет параметров шаблона может быть выведен в пустой пакет, тогда как первый безымянный пакет параметров шаблона class... не является завершающий пакет параметров шаблона.

В GCC ( ошибка 69623 ) и Clang ( ошибка 26435 ) есть ошибки для этой проблемы.

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