Über 2-Dimensionale Arrays iterieren



  • Ich möchte Iteratoren für ein 2-Dimensionales Array benutzen.

    int a[12][34];
    fill(begin(a), end(a), 0); //klappt nicht weil begin(a) ein array is
    fill(begin(*begin(a)), end(*rbegin(a)), 0); //sehr umständlich und rbegin gibts erst ab C++14
    fill(&a[0][0], &a[11][34], 0); //will ich vermeiden
    fill(&a[0][0], &a[0][0] + sizeof a, 0); //meh
    

    Es gibt dafür bestimmt eine ganz einfache und schöne Lösung, ich komm nur nicht drauf.


  • Mod

    Also die rustikale Lösung wäre einfach

    int a[12][34]{};
    

    Edit:

    fill(&a[0][0], &a[0][0] + sizeof a, 0); //meh
    

    ISt das nicht sowieso falsch?



  • Arcoth schrieb:

    Also die rustikale Lösung wäre einfach

    int a[12][34]{};
    

    Edit:

    fill(&a[0][0], &a[0][0] + sizeof a, 0); //meh
    

    ISt das nicht sowieso falsch?

    Per {} initialisieren reicht nicht, da auch sowas wie find_if funktionieren soll.

    fill(&a[0][0], &a[0][0] + sizeof a / sizeof **a, 0); //meh
    

    Jetzt könnte es stimmen, aber schön ist es trotzdem nicht.


  • Mod

    wie wäre es mit

    fill(&**begin(a), &**end(a), 0);
    

    Ansonsten könntest du einfach ein decayed_begin und decayed_end selbst schreiben.
    etwa so

    template <typename T>
    constexpr auto decayed_begin(T&& c) -> decltype(std::begin(std::forward<T>(c)))
    { return std::begin(std::forward<T>(c)); }
    
    template <typename T, std::size_t M, size_t N>
    constexpr auto decayed_begin(T(&&c)[M][N]) -> decltype(decayed_begin(*c))
    { return decayed_begin(*c); }
    
    template <typename T>
    constexpr auto decayed_end(T&& c) -> decltype(std::end(std::forward<T>(c)))
    { return std::end(std::forward<T>(c)); }
    
    template <typename T, std::size_t M, size_t N>
    constexpr auto decayed_end(T(&&c)[M][N]) -> decltype(decayed_begin(c[M]))
    { return decayed_begin(c[M]); }
    


  • Hab mal was gebastelt, unsicher ob das komplett richtig ist:

    template<class T, std::size_t n, typename std::enable_if<std::is_array<T>::value, int>::type = 0>
    typename std::remove_all_extents<T>::type* RecBegin(T(&Array)[n])
    {
    	return RecBegin(Array[0]);
    }
    template<class T, std::size_t n, typename std::enable_if<!std::is_array<T>::value, int>::type = 0>
    T* RecBegin(T(&Array)[n])
    {
    	return &Array[0];
    }
    
    template<class T, std::size_t n, typename std::enable_if<std::is_array<T>::value, int>::type = 0>
    typename std::remove_all_extents<T>::type* RecEnd(T(&Array)[n])
    {
    	return RecEnd(Array[n]);
    }
    template<class T, std::size_t n, typename std::enable_if<!std::is_array<T>::value, int>::type = 0>
    T* RecEnd(T(&Array)[n])
    {
    	return &Array[n];
    }
    

    Edit:
    Das war unnötig kompliziert. Hier eine einfachere Version:

    template<typename T>
    T* RecBegin(T& Object)
    {
    	return &Object;
    }
    template<typename T, std::size_t n>
    typename std::remove_all_extents<T>::type* RecBegin(T(&Array)[n])
    {
    	return RecBegin(Array[0]);
    }
    
    template<typename T>
    T* RecEnd(T& Object)
    {
    	return &Object;
    }
    template<typename T, std::size_t n>
    typename std::remove_all_extents<T>::type* RecEnd(T(&Array)[n])
    {
    	return RecBegin(Array[n]);
    }
    

Anmelden zum Antworten