Шаблоны Variadi c на C ++ и как они работают - PullRequest
0 голосов
/ 28 мая 2020

Итак, я пытаюсь понять, как работают вариативные c шаблоны, поэтому у меня есть этот код:

template <typename Res, typename Type>
void Sum(Res &result, Type &val)
{
    result += val;
}

template <typename Res, typename First, typename... Rest>
void Sum(Res &result, First val1, Rest... valN)
{
    result += val1;
    return Sum(result, valN...);
}

Теперь моя книга говорит, что:

компилятор фактически создает код для правильного типа Sum(), который подходит для вызова, делая это рекурсивно, пока не будут обработаны все аргументы.

Теперь я этого не понимаю, я также пробовал отладку и увидел, что второй функциональный блок Sum вызывается для каждого значения valN, а затем последний вызывает первую Sum() функцию, для меня это не имеет никакого смысла.

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

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

Заранее спасибо.

Ответы [ 2 ]

2 голосов
/ 28 мая 2020

Я думаю, вы могли упустить момент, когда вы проходите через это в отладчике, вы каждый раз вводите совершенно другую функцию.
(Обратите внимание, что val1 не используется в "следующем" вызове , поэтому вы каждый раз передаете на один аргумент меньше.)

Если бы не было вариативных c шаблонов, вам нужно было бы указать их как отдельные шаблоны, но это было бы точно так же:

template <typename Res, typename T>
void Sum(Res& result, T val)
{
    result += val;
}

template <typename Res, typename T1, typename T2>
void Sum(Res& result, T1 val1, T2 val2)
{
    result += val1;
    Sum(result, val2);
}

template <typename Res, typename T1, typename T2, typename T3>    
void Sum(Res& result, T1 val1, T2 val2, T3 val3)
{
    result += val1;
    Sum(result, val2, val3);
}

template <typename Res, typename T1, typename T2, typename T3, typename T4>        
void Sum(Res& result, T1 val1, T2 val2, T3 val3, T4 val4)
{
    result += val1;
    Sum(result, val2, val3, val4);
}

template <typename Res, typename T1, typename T2, typename T3, typename T5>    
void Sum(Res& result, T1 val1, T2 val2, T3 val3, T4 val4, T5 val5)
{
    ...

и так далее, столько, сколько вам нужно.

Шаблон Variadi c заставляет компилятор генерировать все эти «по запросу» и избавляет вас от написания их всех вне.

Один из способов взглянуть на это состоит в том, что обычные шаблоны функций (только с параметрами типа) генерируют перегрузки с тем же количеством параметров; Шаблоныariadi c позволяют вам также создавать перегрузки с различным количеством параметров.

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

1 голос
/ 28 мая 2020

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

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

Вызов функций не является строго обязательным для распаковки, см. cppreference .

Прямой доступ невозможен, потому что это означает, что пакет параметров не является вариативным c. Однако вы всегда можете написать свою версию функции, напрямую ссылающуюся на шаблон любого индекса, просто предоставив целое число шаблона и расширив пакет параметров при уменьшении целого числа (и определив особое поведение, когда оно равно 0).

[Пример вывода частичной суммы по пятому обработанному аргументу вариативного c шаблона]

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