If you want to just iterate over all elements in one loop, then you can do something like this (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