Compile Time For Loops in C++
This is a cool trick I learned from bisqwit’s video.
A typical for loop in C++:
for (auto i = 0UZ; i < N; i++) {
function(I);
}
A very cool compile time for-loop in ISO C++20 (or GNU++17 w/gcc 8+):
[&]<std::size_t ...I>(std::index_sequence<I...>)
{
(function(I), ...);
}
(std::make_index_sequence<N>{});
Which then effectively gets compiled into:
( function(0),
function(1),
function(2),
/* ... */
function(N - 1)
);
The comma operator can be replaced with any other operator in C++, or in the function call as a parameter expansion.
This is useful if function(x)
requires a compile time constant, or for unrolling the loop (but the compiler should do that, not you).
Parameter Expansion
[&]<std::size_t ...I>(std::index_sequence<I...>)
{
function(std::get<I>(params).get() ...);
}
(std::make_index_sequence<std::tuple_size_v<decltype(params)>>{ });
The std::get<N>()
function requires a template parameter, N
, as such it must be some compile-time constant. In this instance, we cannot use a run-time loop, and can opt for this compile-time loop pattern.
Or, we can just:
function(params[0].get(), params[1].get() /* et ad nauseam */);