The standard go-to solution for template-magic is std::index_sequence
.
And for making arguments indexable one uses 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...));
}
Still, if you have static_for()
in your tool-box (you really should), this is simpler:
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...));
});
}
With C++20, one could also write it as:
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...));
}
As an aside, I cut out all the calls to std::forward
, because those rvalue-references would just be reduced down to lvalue-references by the standard-library anyway.