Fiquei meio chocado que ninguém propôs algum loop baseado em magia aritmética para fazer o trabalho. Como C. Wang está procurando uma solução sem loops aninhados , vou propor uma:
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;
}
Bem, esta abordagem não é elegante e flexível, então poderíamos embalar todo o processo em uma função de modelo:
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;
}
}
Esta função de modelo também pode ser expressa na forma de loops aninhados:
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);
}
}
}
}
E pode ser usado fornecendo uma matriz 3D de tamanho arbitrário mais o nome da função, permitindo que a dedução do parâmetro faça o trabalho árduo de contar o tamanho de cada dimensão:
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;
}
Para mais genérico
Mas, mais uma vez, falta flexibilidade porque só funciona para arrays 3D, mas usando SFINAE podemos fazer o trabalho para arrays de uma dimensão arbitrária, primeiro precisamos de uma função de modelo que itera arrays de classificação 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);
}
}
E outro que itera arrays de qualquer classificação, fazendo a recursão:
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);
}
}
Isso nos permite iterar todos os elementos em todas as dimensões de uma matriz de dimensões arbitrárias de tamanho arbitrário.
Trabalhando com std::vector
Para o vetor aninhado múltiplo, a solução se assemelha a um array de dimensões arbitrárias de tamanho arbitrário, mas sem SFINAE: Primeiro, precisaremos de uma função de modelo que itera se std::vector
chame a função desejada:
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);
}
}
E outra função de modelo que itera qualquer tipo de vetor de vetores e se autodenomina:
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);
}
}
Independentemente do nível de aninhamento, iterate_all
chamará a versão do vetor de vetores, a menos que a versão do vetor de valores seja uma correspondência melhor, encerrando assim a recursividade.
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;
}
Eu acho que o corpo da função é bem simples e direto ... Eu me pergunto se o compilador poderia desenrolar esses loops (tenho quase certeza de que a maioria dos compiladores poderia desenrolar o primeiro exemplo).
Veja a demonstração ao vivo aqui .
Espero que ajude.