C++中二维数组中的foreach循环

llmtgqce  于 2023-01-06  发布在  其他
关注(0)|答案(4)|浏览(175)

我有一个3x3的二维数组。我想访问它的所有元素。这可能吗?我这样做:

int myArray[3][3];
for(int &i: myArray){
   //MY CODE HERE.
}

但当我这样做时,我得到错误:

error: C2440: 'initializing' : cannot convert from 'int [3]' to 'int &'

我还在Qt 5.0 x64上使用MSVC++ 2012编译器。如果可以这样做,那么我如何获得每个元素的索引号?

vyu0f0g1

vyu0f0g11#

只需使用auto关键字

int myArray[3][3];

for(auto& rows: myArray) // Iterating over rows
{
    for(auto& elem: rows)
    {
        // do some stuff
    }
}
xpszyzbs

xpszyzbs2#

如果你只想在一个循环中遍历所有元素,那么你可以做如下的事情(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

68de4m5k

68de4m5k3#

#include <iostream>
using namespace std;
int main()
{
    int a[3][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    for (auto &i : a)
    {
        for (auto &j : i)
        {
            cout << j << " ";
        }
        cout << endl;
    }
}
jvlzgdj9

jvlzgdj94#

int*换成int&就行了

int myArray[3][3];

for(int* rows: myArray) // Iterating over rows
{
    for(int* elem: rows)
    {
        // do some stuff
    }
}

相关问题