#c #variadic-templates #typetraits
#c #переменные-шаблоны #признаки типов
Вопрос:
У меня есть следующий код с шаблоном переменной, скопированным из: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 () ограничивает использование всего шаблона целыми числами — Могу ли я расширить тот же шаблон для объединения строк?
Спасибо
Комментарии:
1. Означает ли тег C 14, что вы не хотите слышать о C 17-кратных выражениях?
2. Нет — Я согласен с C 17
Ответ №1:
В дополнение к ответу @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;
}
Вы также можете рассмотреть выражения fold:
template<typename ...Pack>
auto sum(Pack... args) {
return (args ...);
}
Комментарии:
1. Если вы работаете на C 17, вы могли бы также использовать выражение fold …
Ответ №2:
Хитрость заключается в том, чтобы никогда не разрешать пустые 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;
}
Ответ №3:
- Здесь требуется
sum()
функция, чтобы я мог возвращать значение дляvoid
переданного при обработке последнего элемента переменной — Возможно ли избежать написания этойsum()
функции и иметь ту же функциональность?
Для каждой рекурсии требуется условие остановки. При типичном использовании рекурсии с шаблонами переменных (например, в этом коде) условием остановки является другая перегрузка основного шаблона. Таким образом, вы не можете полностью избавиться от этого.
Вы, конечно, можете заменить условие остановки другим. Возможно, этот, который также будет работать для суммирования вещей, которые не могут быть сконструированы по умолчанию:
template <class T>
auto sum(T last) { return last; }
Конечно, существуют другие подходы к этому, чем рекурсивные шаблоны переменных; для таких подходов может не потребоваться условие остановки.
- Возврат целого числа ‘0’ из
sum()
функции ограничивает использование всего шаблона целыми числами — Могу ли я расширить тот же шаблон для объединения строк?
Нет, потому что не шаблонная функция не знает, с каким типом имели дело предыдущие рекурсивные вызовы. Это можно решить, используя условие остановки «последнего элемента», которое я предложил выше.
Комментарии:
1. Как работает решение с
return {};
? Я не могу заставить это работать: ideone.com/vrCXSb2. @mch Конечно, это была ошибка с моей стороны. Исправлено.