提问人:Danny 提问时间:11/5/2023 最后编辑:Danny 更新时间:11/7/2023 访问量:57
如何实现能够返回生成器的模板驱动的嵌套 for 循环?
How can I implement a template-driven nested for-loop that is capable of returning a generator?
问:
我正在尝试实现一个在多维数组上提供下标的生成器。具体来说,我正在使用 CPP Chrono 的生成器实现。由于维数由输入数组的大小决定,因此我需要一个递归函数来生成嵌套循环。到目前为止,我的逻辑适用于一个大小扣除的嵌套 for 循环:shape
for
#include <iostream>
#include <array>
using Size_t = size_t;
using Int64_t = int;
/// @brief Nested for loop helper
/// @details Recursively generates NLoops nested for loops
template <size_t Index = 0, Size_t NLoops>
void nested_for_loop(const std::array<Size_t, NLoops>& shape, std::array<Int64_t, NLoops>& outSubscripts) {
if constexpr (Index == NLoops) {
// Base case: All nested loops have run.
// Operation is performed here
for (size_t i = 0; i < NLoops; ++i) {
std::cout << outSubscripts[i] << ' ';
}
std::cout << std::endl;
} else {
// Recursive case: Loop from 0 to array[Index]
for (size_t i = 0; i <= shape[Index]; ++i) {
outSubscripts[Index] = i; // Store the current subscript
nested_for_loop<Index + 1>(shape, outSubscripts); // Recursively call for the next loop
}
}
}
int main() {
std::array<Size_t, 3> shape = {2, 30, 6};
std::array<int, 3> outSubscripts{};
Int64_t outIndex = 0;
nested_for_loop(shape, outSubscripts);
return 0;
}
这能够打印出我想要的下标。如果这只是一个常规的旧 for 循环,我可以在操作逻辑所在的位置添加一个,将函数返回类型更新为 ,然后调用它。但是,似乎不可能将这种递归方法转换为生成器函数。co_yield
generator<MyDesiredArrayType>
有没有更好的方法来展开这个循环,以便我可以正确地从协程中产生?我唯一能想到的方法就是这个答案中描述的方法。我宁愿不必求助于这样的东西,因为我认为没有一种方法可以将线性循环索引转换为所需的下标,而且我不想产生额外的加法/乘法的运行时成本。for
constexpr
N
我总是可以选择手动写出一系列语句。我可以添加条件块,所以我会支持从 0 到嵌套的 for 循环。然而,这将是如此乏味和限制,以至于它是愚蠢的。肯定有更好的方法!if constexpr
M
M
答:
0赞
Jarod42
11/7/2023
#1
您可以将递归函数转换为简单的迭代函数:
template <std::size_t N>
bool next_cartesian_product(const std::array<std::size_t, N>& shape,
std::array<std::size_t, N>& cur)
{
for (std::size_t i = 0; i != N; ++i) {
if (++cur[N - 1 - i] > shape[N - 1 - i]) {
cur[N - 1 - i] = 0;
} else {
return true;
}
}
return false;
}
现在把它变成发电机应该是微不足道的。
上一个:中断并继续功能
评论