没有人提出基于算术魔术的循环来完成这项工作,我感到非常震惊。 由于C. Wang在寻找没有嵌套循环的解决方案,因此我将提出一个解决方案:
double B[10][8][5];
int index = 0;
while (index < (10 * 8 * 5))
{
const int x = index % 10,
y = (index / 10) % 10,
z = index / 100;
do_something_on_B(B[x][y][z]);
++index;
}
好的,这种方法不够灵活,因此我们可以将所有过程打包到一个模板函数中:
template <typename F, typename T, int X, int Y, int Z>
void iterate_all(T (&xyz)[X][Y][Z], F func)
{
const int limit = X * Y * Z;
int index = 0;
while (index < limit)
{
const int x = index % X,
y = (index / X) % Y,
z = index / (X * Y);
func(xyz[x][y][z]);
++index;
}
}
此模板函数也可以嵌套循环的形式表示:
template <typename F, typename T, int X, int Y, int Z>
void iterate_all(T (&xyz)[X][Y][Z], F func)
{
for (auto &yz : xyz)
{
for (auto &z : yz)
{
for (auto &v : z)
{
func(v);
}
}
}
}
并可以用来提供任意大小的3D数组加上函数名,让参数推导完成计算每个维度大小的艰巨工作:
int main()
{
int A[10][8][5] = {{{0, 1}, {2, 3}}, {{4, 5}, {6, 7}}};
int B[7][99][8] = {{{0, 1}, {2, 3}}, {{4, 5}, {6, 7}}};
iterate_all(A, do_something_on_A);
iterate_all(B, do_something_on_B);
return 0;
}
走向更通用
但是又一次,它缺乏灵活性,因为它仅适用于3D数组,但是使用SFINAE,我们可以对任意维度的数组进行处理,首先,我们需要一个模板函数来迭代等级 1的数组:
template<typename F, typename A>
typename std::enable_if< std::rank<A>::value == 1 >::type
iterate_all(A &xyz, F func)
{
for (auto &v : xyz)
{
func(v);
}
}
另一个迭代任何级别的数组,进行递归:
template<typename F, typename A>
typename std::enable_if< std::rank<A>::value != 1 >::type
iterate_all(A &xyz, F func)
{
for (auto &v : xyz)
{
iterate_all(v, func);
}
}
这使我们可以迭代任意维度任意大小数组的所有维度中的所有元素。
与...合作 std::vector
对于多重嵌套向量,该解决方案类似于任意维度的任意大小的数组,但没有SFINAE:首先,我们需要一个迭代std::vector
s并调用所需函数的模板函数:
template <typename F, typename T, template<typename, typename> class V>
void iterate_all(V<T, std::allocator<T>> &xyz, F func)
{
for (auto &v : xyz)
{
func(v);
}
}
还有另一个模板函数,可以迭代任何种类的向量并调用自己:
template <typename F, typename T, template<typename, typename> class V>
void iterate_all(V<V<T, std::allocator<T>>, std::allocator<V<T, std::allocator<T>>>> &xyz, F func)
{
for (auto &v : xyz)
{
iterate_all(v, func);
}
}
无论嵌套级别如何,iterate_all
都将调用向量矢量版本,除非向量值版本更好地匹配,从而结束递归性。
int main()
{
using V0 = std::vector< std::vector< std::vector<int> > >;
using V1 = std::vector< std::vector< std::vector< std::vector< std::vector<int> > > > >;
V0 A0 = {{{0, 1}, {2, 3}}, {{4, 5}, {6, 7}}};
V1 A1 = {{{{{9, 8}, {7, 6}}, {{5, 4}, {3, 2}}}}};
iterate_all(A0, do_something_on_A);
iterate_all(A1, do_something_on_A);
return 0;
}
我认为函数主体非常简单明了……我想知道编译器是否可以展开此循环(我几乎可以确定大多数编译器都可以展开第一个示例)。
在这里观看现场演示。
希望能帮助到你。