Стандартное решение для магии шаблонов: std::index_sequence
.
А для доведения аргументов до индексируемых используется std::tuple
.
template <std::size_t... N, class T>
void print_reverse_impl(std::index_sequence<N...>, std::ostream& os, T t) {
(os << ... << std::get<std::tuple_size_v<T> - N - 1>(t));
}
template <class... T>
void print_reverse(std::ostream& os, T&&... t) {
print_reverse_impl(std::make_index_sequence<sizeof...(t)>(), os, std::forward_as_tuple(t...));
}
Тем не менее, если у вас есть static_for()
в вашем наборе инструментов (вы действительно должны это сделать), это проще:
template <class... T>
void print_reverse(std::ostream& os, T&&... t) {
static_for<sizeof...(t)>([&](auto n){
os << std::get<sizeof...(t) - n - 1>(std::forward_as_tuple(t...));
});
}
С C ++ 20 можно также написать это как:
void print_reverse(std::ostream& os, auto&&... t) {
[&]<auto... N>(std::index_sequence<N...>, auto all){
(os << ... std::get<sizeof...(t) - N - 1>(all));
}(std::make_index_sequence<sizeof...(t)>(), std::forward_as_tuple(t...));
}
Кроме того, я отключил все вызовы к std::forward
, потому что эти ссылки на rvalue были бы просто уменьшены до ссылок на lvalue посредством стандартной библиотеки в любом случае.