나는 아무도 그 작업을 수행하기 위해 어떤 산술 마술 기반 루프를 제안하지 않았다는 사실에 다소 충격을 받았습니다. 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;
}
함수 본문이 매우 간단하고 간단하다고 생각합니다. 컴파일러가이 루프를 풀 수 있는지 궁금합니다 (대부분의 컴파일러가 첫 번째 예제를 풀 수 있다고 거의 확신합니다).
여기에서 라이브 데모를 참조 하십시오 .
도움이되기를 바랍니다.