Как сделать шаблонный цикл?

Я очень часто вожусь с циклами и они почти одинаковые, думаю что можно упростить много кода если будет один шаблон.

// блоки могут быть разные но число заранее известно до компиляции
const int block_1 = 10,
          block_2 = 4,
          block_3 = 6,
          block_4 = 3;

В основном все циклы такие

цикл может быть такой

for (int i = 1; i < block_1 - 1; ++i) {

}

или такой

for (int i = 1; i < block_1 - 1; ++i) {
    for (int k = 1; k < block_2 - 1; ++k) {

    }
}

или такой

for (int i = 1; i < block_1 - 1; ++i) {
    for (int k = 1; k < block_2 - 1; ++k) {
        for (int j = 1; j < block_3 - 1; ++j) {
          // тут пишу код 

        }
    }
}

Количество циклов внутри цикла может быть много, а так они похоже

Я вот думаю что если не делать постоянно циклы а использовать шаблон, будет ли это удобней или нет, но возможно не стоит и вы меня отговорите это делать.

В идеале я бы хотел вот такой шаблон

for_funk(block_1, block_2, block_3) {
   // тут пишу код который будет внутри трех циклов block_1, block_2, block_3
}

Возможно это поможет https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2374r4.html


Ответы (1 шт):

Автор решения: Алексей Саровский

Чисто из академического интереса попробовал подобную конструкцию реализовать, через рекурсию в принципе такое возможно, рабочий пример прикладываю (его точно можно упростить, делал на коленке).

template<typename Callback, int Index, int Head, int... Tail>
void F(int counters[], Callback cbk)
{
    for (counters[Index] = 0; counters[Index] < Head; ++counters[Index])
    {
        if constexpr (sizeof...(Tail) > 0)
            F<Callback, Index + 1, Tail...>(counters, cbk);
        else
            cbk(counters);
    }
}

template<int... N>
void F(std::function<void(int counters[sizeof...(N)])> cbk)
{
    int counters[sizeof...(N)];
    F<std::function<void(int counters[sizeof...(N)])>, 0, N...>(counters, cbk);
}

int main()
{
    F<1, 2, 3>([](int counters[3]){ std::cout << counters[0] << " " << counters[1] << " " << counters[2] << std::endl; });
}
→ Ссылка