Вывод аргументов шаблона при частичном упорядочении, когда параметры являются пакетом параметров функции

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}

Обе функции занимают три ints по значению, поэтому все обычные прерыватели связей в разрешении перегрузки не могут разрешить неоднозначность. Итак, мы дошли до самого последнего:

Учитывая эти определения, жизнеспособная функция 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.

Другие вопросы по тегам