如果您只想在一个循环中迭代所有元素,那么您可以执行以下操作(C++11):
#include <type_traits>
#include <algorithm>
#include <cstdint>
#include <cstdlib>
#include <cstdio>
#if defined(__clang__)
# define UTILITY_COMPILER_CXX_CLANG
# define UTILITY_COMPILER_CXX_VERSION __clang_major__
# define UTILITY_COMPILER_CXX_VERSION_MINOR __clang_minor__
# define UTILITY_COMPILER_CXX_VERSION_PATCHLEVEL __clang_patchlevel__
# if __clang_major__ < 3
# error unsuported clang version
# endif
#elif defined(__GNUC__)
# define UTILITY_COMPILER_CXX_GCC
# define UTILITY_COMPILER_CXX_VERSION __GNUC__
# define UTILITY_COMPILER_CXX_VERSION_MINOR __GNUC_MINOR__
# define UTILITY_COMPILER_CXX_VERSION_PATCHLEVEL __GNUC_PATCHLEVEL__
# if __GNUC__ < 4
# error unsuported gcc version
# endif
#elif defined(_MSC_VER)
# define UTILITY_COMPILER_CXX_MSC
# define UTILITY_COMPILER_CXX_VERSION _MSC_VER
#else
# error unknown compiler
#endif
#ifdef UTILITY_COMPILER_CXX_MSC
# if UTILITY_COMPILER_CXX_VERSION >= 1900
# define UTILITY_PLATFORM_FEATURE_CXX_STANDARD_CONSTEXPR
# endif
#else
# if __cplusplus >= 201103L
# ifdef UTILITY_COMPILER_CXX_GCC // specific case for GCC 4.7.x and lower
# if UTILITY_COMPILER_CXX_VERSION >= 5 || \
UTILITY_COMPILER_CXX_VERSION == 4 && UTILITY_COMPILER_CXX_VERSION_MINOR >= 8
# define UTILITY_PLATFORM_FEATURE_CXX_STANDARD_CONSTEXPR
# endif
# else
# define UTILITY_PLATFORM_FEATURE_CXX_STANDARD_CONSTEXPR
# endif
# endif
#endif
#ifdef UTILITY_PLATFORM_FEATURE_CXX_STANDARD_CONSTEXPR
# define CONSTEXPR constexpr
#else
# define CONSTEXPR
#endif
namespace utility
{
// bool identity / identities
template <bool b>
struct bool_identity
{
using type = bool;
static CONSTEXPR const bool value = b;
};
template <bool b>
CONSTEXPR const bool bool_identity<b>::value;
// Unrolled breakable `for_each` for multidimensional arrays
namespace detail
{
template<bool is_array>
struct _for_each_unroll
{
template <typename Functor, typename T, std::size_t N>
_for_each_unroll(_for_each_unroll * parent_, T (& arr)[N], Functor && f) :
parent(parent_), break_(false)
{
invoke(arr, std::forward<Functor>(f));
}
template <typename Functor, typename T, std::size_t N>
_for_each_unroll(_for_each_unroll * parent_, T (&& arr)[N], Functor && f) :
parent(parent_), break_(false)
{
invoke(std::forward<T[N]>(arr), std::forward<Functor>(f));
}
template <std::size_t I = 0, typename Functor, typename T, std::size_t N>
typename std::enable_if<I == N, void>::type
invoke(T (& arr)[N], Functor && f)
{
}
template <std::size_t I = 0, typename Functor, typename T, std::size_t N>
typename std::enable_if<I == N, void>::type
invoke(T (&& arr)[N], Functor && f)
{
}
template <std::size_t I = 0, typename Functor, typename T, std::size_t N>
typename std::enable_if<I < N, void>::type
invoke(T (& arr)[N], Functor && f)
{
if (!break_) {
_for_each_unroll<std::is_array<T>::value> nested_for_each{ this, arr[I], std::forward<Functor>(f) };
if (!nested_for_each.break_) {
invoke<I + 1, Functor, T, N>(arr, std::forward<Functor>(f));
}
else if (parent) parent->break_ = true;
}
}
template <std::size_t I = 0, typename Functor, typename T, std::size_t N>
typename std::enable_if<I < N, void>::type
invoke(T (&& arr)[N], Functor && f)
{
if (!break_) {
_for_each_unroll<std::is_array<T>::value> nested_for_each{ this, std::forward<T>(arr[I]), std::forward<Functor>(f) };
if (!nested_for_each.break_) {
invoke<I + 1, Functor, T, N>(arr, std::forward<Functor>(f));
}
else if (parent) parent->break_ = true;
}
}
_for_each_unroll * parent;
bool break_;
};
template <typename Functor, typename T, bool is_array>
inline void _invoke_breakable(_for_each_unroll<is_array> & this_, const T & value, Functor && f, bool_identity<false> is_breakable)
{
f(value);
};
template <typename Functor, typename T, bool is_array>
inline void _invoke_breakable(_for_each_unroll<is_array> & this_, const T & value, Functor && f, bool_identity<true> is_breakable)
{
if (!f(value)) {
this_.break_ = true;
}
};
template <typename Functor, typename T, bool is_array>
inline void _invoke_breakable(_for_each_unroll<is_array> & this_, T && value, Functor && f, bool_identity<false> is_breakable)
{
f(std::forward<T>(value));
};
template <typename Functor, typename T, bool is_array>
inline void _invoke_breakable(_for_each_unroll<is_array> & this_, T && value, Functor && f, bool_identity<true> is_breakable)
{
if (!f(std::forward<T>(value))) {
this_.break_ = true;
}
};
template<>
struct _for_each_unroll<false>
{
template <typename Functor, typename T>
_for_each_unroll(void * parent, const T & value, Functor && f) :
break_(false)
{
_invoke_breakable(*this, value, std::forward<Functor>(f), bool_identity<!std::is_void<decltype(f(value))>::value>{});
}
template <typename Functor, typename T>
_for_each_unroll(void * parent, T && value, Functor && f) :
break_(false)
{
_invoke_breakable(*this, value, std::forward<Functor>(f), bool_identity<!std::is_void<decltype(f(std::forward<T>(value)))>::value>{});
}
bool break_;
};
}
template <std::size_t I = 0, typename Functor, typename T, std::size_t N>
inline typename std::enable_if<I == N, void>::type
for_each_unroll(T (& arr)[N], Functor && f)
{
}
template <std::size_t I = 0, typename Functor, typename T, std::size_t N>
inline typename std::enable_if<I == N, void>::type
for_each_unroll(T (&& arr)[N], Functor && f)
{
}
template <std::size_t I = 0, typename Functor, typename T, std::size_t N>
inline typename std::enable_if<I < N, void>::type
for_each_unroll(T (& arr)[N], Functor && f)
{
detail::_for_each_unroll<std::is_array<T>::value> nested_for_each{ nullptr, arr[I], std::forward<Functor>(f) };
if (!nested_for_each.break_) {
for_each_unroll<I + 1, Functor, T, N>(arr, std::forward<Functor>(f));
}
}
template <std::size_t I = 0, typename Functor, typename T, std::size_t N>
inline typename std::enable_if<I < N, void>::type
for_each_unroll(T (&& arr)[N], Functor && f)
{
detail::_for_each_unroll<std::is_array<T>::value> nested_for_each{ nullptr, std::forward<T>(arr[I]), std::forward<Functor>(f) };
if (!nested_for_each.break_) {
for_each_unroll<I + 1, Functor, T, N>(std::forward<T[N]>(arr), std::forward<Functor>(f));
}
}
}
int main()
{
int i = 0;
int a[2][3][4] = { 0 };
utility::for_each_unroll(a, [&](int & value) {
value = i;
i++;
});
for (auto & j0 : a) for (auto & j1 : j0) for (auto & j2 : j1) printf("%u ", j2);
puts("\n");
i = 0;
int b[2][3][4] = { 0 };
utility::for_each_unroll(b, [&](int & value) {
value = i;
i++;
if (i >= 3) return false;
return true;
});
for (auto & j0 : b) for (auto & j1 : j0) for (auto & j2 : j1) printf("%u ", j2);
}
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
0 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
https://godbolt.org/z/oEPf4GMsz