Шаблоны Variadic - Рекурсивная функция - Последний член Variadic - PullRequest
4 голосов
/ 06 марта 2019

У меня есть следующий код с шаблоном переменной, скопированным из: https://www.youtube.com/watch?v=iWvcoIKSaoc @ 41: 30

auto sum() { return 0; }

template<typename Head, typename... Tail>
auto sum(Head head, Tail... tail)
{
    return head+sum(tail...);
}

int main() {
    cout<< sum(1,2.4) << endl;
    //cout<< sum("hello ", "world") << endl;
    return 0;
}

У меня есть два вопроса: 1. Функция sum () здесь нужначто я могу получить возвращаемое значение для void, переданного при обработке последнего члена переменной - возможно ли избежать написания этой функции sum () и иметь такую ​​же функциональность?

Возвращение целого числа '0' из функции sum () ограничивает использование целого шаблона целыми числами. Можно ли расширить этот шаблон для объединения строк?

Спасибо

Ответы [ 3 ]

6 голосов
/ 06 марта 2019

В дополнение к ответу @GuillaumeRacicot я предпочитаю заканчивать рекурсию с помощью if constexpr, которая является c++17 функцией.

template<typename Head, typename Second, typename... Tail>
auto sum(Head head, Second second, Tail... tail)
{ 
    if constexpr(sizeof...(tail) > 0)
      return head + sum(second, tail...);
    return head + second;
}

Вы также можете рассмотреть выражения сгиба:

template<typename ...Pack>
auto sum(Pack... args) {
    return (args + ...);
}
3 голосов
/ 06 марта 2019

Хитрость заключается в том, чтобы никогда не разрешать пустые sum() вызовы и обрабатывать sum(last) как последнюю рекурсию:

template<typename Last>
auto sum(Last last) {
    return last;
}

template<typename Head, typename Second, typename... Tail>
auto sum(Head head, Second second, Tail... tail)
{
    return head + sum(second, tail...);
}

int main() {
    cout<< sum(1,2.4) << endl;
    cout<< sum("hello ", "world") << endl;
    return 0;
}

Живой пример

1 голос
/ 06 марта 2019
  1. Функция sum() требуется здесь, чтобы я мог получить возвращаемое значение для void, переданного при обработке последнего элемента с переменным числом. - Можно ли избежать написания этой функции sum() и иметь такую ​​же функциональность?

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

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

template <class T>
auto sum(T last) { return last; }

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

  1. Возвращение целого числа '0' из функции sum() ограничивает использование целого шаблона целыми числами. Могу ли я расширить этот же шаблон для объединения строк?

Нет, поскольку не шаблонная функция не знает, с каким типом имели дело предыдущие рекурсивные вызовы. Эту проблему можно решить с помощью условия остановки «последний элемент», которое я предложил выше.

...