我尝试实现一个采用以下参数的函数
template <FUNC>
compute_in_D_dims(int D, FUNC f, int N)
哪里
我希望为序列 0 到 N-1 中的 D 个数字创建具有重复的排列
所以当 D = 3 时,它看起来像
for (int i = 0; i < N; ++i)
for (int j = 0; j < N; ++j)
for (int k = 0; k < N; ++k)
f(i, j, k)
现在 D 作为参数提供,并且是先验未知的 。此外,D 可能很大,这使得深度嵌套循环的编写不太可行。
我的想法是,对于排列,存在到数字 I 的双射映射,因为我有 N^D 个排列,并且我可以对它们进行计数。
回到我的示例,D = 3,N = 2,我的排列如下
0 0 0
0 0 1
0 1 0
1 1 1
1 0 0
1 0 1
和
bijection(n) = // implement function
将返回第 5 个索引(从 0 开始计数)
bijection(5) = {1, 0, 1}
现在是最困难的部分:
如何将返回元组/向量/...传递给提供的函数?
它可能是 2 个元素或 10 个元素,我对如何将 D-many 参数传递给函数一无所知。此外,由于函数作为参数给出,我无法控制它。
我听说过“可变参数函数”的提示,但我对它到底是什么以及如何开始一无所知。
你不需要一个可变参数函数。据我所知,可变参数函数是接受 n 个参数并相应地使用它们的函数。它们有助于管理手动制作时有些(会变得)混乱的代码。
现在,对于答案,我之前在练习 C++ 和排列时也做过同样的事情,我发现,你不需要可变数量的循环。相反,您可以只计算将会出现的排列数量
P(n,r)= 1*2*...*n
。这将告诉您需要为排列值进行多少次循环。然后,您可以初始化大小为 D 的 int 向量并用 0 填充它(因为第一个值为 0,0,0)。在下一个循环中,您可以像这样调用函数 f
:
std::vector<int> indices(D, 0); //filling the vector with size D with only 0's
f(indices[0], indices[1], indices[2]);
然后您可以根据
N
的值更新这三个值。喜欢:
for (int j = D - 1; j >= 0; --j) {
indices[j]++;
if (indices[j] < N)
break;
indices[j] = 0;
}
因此,总共只有 3 个 for 循环,一个用于计算排列数量,第二个用于调用函数,第三个(这是第二个循环的嵌套循环)更新索引。
我根据你的函数想法制作的函数:
template <typename FUNC>
void compute_in_D_dims(int D, FUNC f, int N) {
std::vector<int> indices(D, 0);
int total_permutations = 1;
for (int i = 0; i < D; ++i)
total_permutations *= N;
for (int i = 0; i < total_permutations; ++i) {
f(indices[0], indices[1], indices[2]);
for (int j = D - 1; j >= 0; --j) {
indices[j]++;
if (indices[j] < N)
break;
indices[j] = 0;
}
}
}
我希望这有帮助!这对我有用。告诉我它是否适合你。
编辑:
我认为我误解了这个问题,并以硬编码的方式做到了这一点,正如@Fareanor 所指出的。
您可以修改函数 f ,使其接受 int 向量,而不是 D 个参数。
喜欢:
for (int i = 0; i < total_permutations; ++i) {
f(indices);
//the rest of the code
}
这样,你就可以这样做:
//assuming your function prints the args
void f(std::vector<int> indices)
{
for(auto id:indices)
{
std::cout<< id<<" ";
}
std::cout<<std::endl;//for the next permutation
}