Consider this code:
template < size_t... Indices >
void something(std::index_sequence<Indices...>)
{
// how to obtain the following call where N is sizeof...(Indices)?
// foo(f(0),g(0),f(1),g(1),...,f(N-1),g(N-1));
}
The key to answering a question like:
// how to obtain the following call where N is sizeof...(Indices)?
// foo(f(0),g(0),f(1),g(1),...,f(N-1),g(N-1));
is to formulate how to actually generate such a pack expansion. We have 2N
arguments, which would like:
+=====+======+
| idx | expr |
+-----+------+
| 0 | f(0) |
| 1 | g(0) |
| 2 | f(1) |
| 3 | g(1) |
| ....
+=====+======+
In C++17, we can write such an expression with if constexpr
:
template <size_t I>
auto expr() {
if constexpr (I % 2 == 0) {
// even indices are fs
return f(I / 2);
} else {
// odds are gs
return g(I / 2);
}
}
Which can even be a lambda that takes an integral_constant
as an argument. So we really just need to turn our N
arguments into 2N
arguments, which is just a matter of adding more indices:
template <auto V>
using constant = std::integral_constant<decltype(V), V>;
template < size_t... Indices >
void something(std::index_sequence<Indices...>) {
auto expr = [](auto I) {
if constexpr (I % 2 == 0) {
return f(I / 2);
} else {
return g(I / 2);
}
}
return foo(
expr(constant<Indices>{})..., // 0, ..., N-1
expr(constant<Indices + sizeof...(Indices)>{})... // N, ..., 2N-1
);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With