Вывод аргументов шаблона при частичном упорядочении, когда параметры являются пакетом параметров функции
N4527 14.8.2.4 [temp.deduct.partial]
3 Типы, используемые для определения порядка, зависят от контекста, в котором выполняется частичное упорядочение:
(3.1) - В контексте вызова функции используются типы типов параметров функции, для которых вызов функции имеет аргументы.
(3.2) - В контексте вызова функции преобразования используются типы возврата шаблонов функций преобразования.
(3.3) - В других контекстах (14.5.6.2) используется тип функции шаблона функции.
4 Каждый тип, назначенный выше из шаблона параметра, и соответствующий тип из шаблона аргумента используются в качестве типов
P
а такжеA
,8 Если
A
был преобразован из пакета параметров функции иP
не является пакетом параметров, вывод типа завершается ошибкой. В противном случае, используя результирующие типыP
а такжеA
затем производится вычет, как описано в 14.8.2.5. ЕслиP
это пакет параметров функции, типA
каждого оставшегося типа параметра шаблона аргумента сравнивается с типомP
из объявления-идентификатора пакета параметров функции. Каждое сравнение выводит аргументы шаблона для последующих позиций в пакетах параметров шаблона, расширенных пакетом параметров функции. Если для данного типа вывод выполняется успешно, считается, что тип из шаблона аргумента является по меньшей мере таким же специализированным, как и тип из шаблона параметра. [ Пример:
template<class... Args> void f(Args... args); // #1
template<class T1, class... Args> void f(T1 a1, Args... args); // #2
template<class T1, class T2> void f(T1 a1, T2 a2); // #3
f(); // calls #1
f(1, 2, 3); // calls #2
f(1, 2); // calls #3; non-variadic template #3 is more
// specialized than the variadic templates #1 and #2
Зачем f(1, 2, 3);
звонки № 2?
Мне нужно больше деталей, в том числе:
1 Какой это контекст?
2 Какие трансформированы из?
например, преобразованный из #1 является void (U)
, void (U...)
или другая форма?(U
означает уникальный тип)
14.5.6.2 [temp.func.order] / p3
Чтобы создать преобразованный шаблон, для каждого типа, не типового или шаблонного параметра шаблона (включая его пакеты параметров шаблона (14.5.3)) синтезируйте уникальный тип, значение или шаблон класса соответственно и подставьте его для каждого вхождения этого параметра. в типе функции шаблона.
3 Какие бывают типы P
а также A
используется в удержании? например
template <class T> void f(T);
int a = 1;
f(a);//P = T, A = int
1 ответ
Зачем
f(1, 2, 3);
звонки № 2?
В вашем вопросе много вопросов (по одному на каждый вопрос, пожалуйста!), Поэтому я буду придерживаться этого. Сначала мы выполняем шаблонное вычитание. #3 терпит неудачу, но #1 и #2 успешно:
template<class... Args>
void f(Args... args); // #1, with Args = {int, int, int}
template<class T1, class... Args>
void f(T1 a1, Args... args); // #2, with T1 = int, Args = {int, int}
Обе функции занимают три int
s по значению, поэтому все обычные прерыватели связей в разрешении перегрузки не могут разрешить неоднозначность. Итак, мы дошли до самого последнего:
Учитывая эти определения, жизнеспособная функция
F1
определяется как лучшая функция, чем другая жизнеспособная функцияF2
если для всех аргументовi
, ICSя(F1
) не хуже последовательности преобразования, чем ICSi(F2
), а потом
- [...]
-F1
а такжеF2
являются специализациями шаблонов функций, а шаблон функций дляF1
более специализирован, чем шаблон дляF2
в соответствии с правилами частичного заказа, описанными в 14.5.6.2.
Правила таковы:
Шаг 1: синтезировать типы [temp.func.order]:
Чтобы создать преобразованный шаблон, для каждого типа, не типового или шаблонного параметра шаблона (включая его пакеты параметров шаблона (14.5.3)) синтезируйте уникальный тип, значение или шаблон класса соответственно и подставьте его для каждого вхождения этого параметра. в типе функции шаблона.
Итак, мы имеем:
void f(Pack1... args); // #1
void f(U2 a1, Pack2... args); // #2
Шаг 2: выполните удержание, как описано в [temp.deduct.partial]. Контекст, в котором мы находимся, является вызовом функции, поэтому мы используем типы, для которых вызов функции имеет аргументы.
Сначала мы пытаемся вывести № 2 из № 1. То есть мы пытаемся соответствовать (T1, Args...
) против (Pack1...)
, Первая часть тогда P = T1, A = Pack1...
, У нас есть:
Если A был преобразован из пакета параметров функции, а P не является пакетом параметров, вывод типа завершается ошибкой.
Таким образом, выведение #2 из #1 терпит неудачу, поэтому аргумент Args...
по крайней мере, не так специализирован, как T1, Args...
,
Далее мы пытаемся вывести № 1 из № 2. То есть мы стараемся соответствовать (Args...)
против (U2, Pack2...)
, Это удается, так T1, Args...
по крайней мере так же специализирован, как Args...
,
Поскольку #2, по крайней мере, столь же специализирован, как #1, а #1, по крайней мере, не так специализирован, как #2, мы можем сказать, что #2 более специализирован:
Шаблон функции
F
по крайней мере так же специализирован, как шаблон функцииG
если для каждой пары типов, используемых для определения порядка, тип изF
по крайней мере так же специализирован, как тип изG
,F
более специализированный, чемG
еслиF
по крайней мере так же специализирован, какG
а такжеG
по крайней мере, не так специализирован, какF
,
Более специализированный шаблон предпочтительнее, поэтому мы называем #2.