5

I wrote a c++ program as fllow(3.43.cpp):

#include <iostream>
using std::cout;
using std::endl;

void version_1(int **arr) {
    for (const int (&p)[4] : arr) {
        for (int q : p) {
            cout << q << " ";
        }
        cout << endl;
    }
}

int main() {
    int arr[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
    version_1(arr);
    return 0;
}

Then I compile it by using: gcc my.cpp -std=c++11, there is an error I can not deal with. Info:

3.43.cpp:6:30: error: no matching function for call to ‘begin(int**&)’
     for (const int (&p)[4] : arr) {
                              ^
3.43.cpp:6:30: note: candidates are:
In file included from /usr/include/c++/4.8.2/bits/basic_string.h:42:0,
                 from /usr/include/c++/4.8.2/string:52,
                 from /usr/include/c++/4.8.2/bits/locale_classes.h:40,
                 from /usr/include/c++/4.8.2/bits/ios_base.h:41,
                 from /usr/include/c++/4.8.2/ios:42,
                 from /usr/include/c++/4.8.2/ostream:38,
                 from /usr/include/c++/4.8.2/iostream:39,
                 from 3.43.cpp:1:
/usr/include/c++/4.8.2/initializer_list:89:5: note: template<class _Tp> constexpr const _Tp* std::begin(std::initializer_list<_Tp>)
     begin(initializer_list<_Tp> __ils) noexcept

I search it in google, but not find similar answer.

Barry
  • 247,587
  • 26
  • 487
  • 819
Sparks_Fly
  • 359
  • 3
  • 14
  • See [passing 2D array to function](http://stackoverflow.com/questions/8767166/passing-2d-array-to-function) . Also you are missing aguments in your call to `version_1`... – quantdev Dec 14 '14 at 03:27
  • Change the parameter type to `const int (&arr)[3][4]` and get rid of the other two parameters. – 0x499602D2 Dec 14 '14 at 03:29
  • Ranged-based for loop can only be used on something for which `std::begin(x)` and `std::end(x)` are valid – M.M Dec 14 '14 at 03:37
  • @quantdev I deleted the aguments in my local program, but fogot to delete here, I have changed it. Thank you! – Sparks_Fly Dec 14 '14 at 04:12
  • Why not use something sane... like a vector? – Mark Dec 14 '14 at 07:47

3 Answers3

13

Since arr is just a pointer, there's no way to deduce how big it is. But, since you are actually passing in a real array, you can just template your function on its dimensions so you take the actual array by reference rather than having it decay to a pointer:

template <size_t X, size_t Y>
void foo(const int (&arr)[X][Y])
{
    std::cout << "Dimensions are: " << X << "x" << Y << std::endl;

    for (const int (&row)[Y] : arr) {
        for (int val : row) {
            std::cout << val << ' ';
        }
        std::cout << std::endl;
    }
}

int main() {
    int arr[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
    foo(arr);
}
Barry
  • 247,587
  • 26
  • 487
  • 819
  • 2
    of course, the type specifier for the loop variables can be replaced by `auto &` – M.M Dec 14 '14 at 03:37
  • @MattMcNabb Yes, but I wanted to illustrate what the types were to the OP for clarity. – Barry Dec 14 '14 at 03:39
  • The range based for is equivalent to an iteration from begin(container) to end(container). Please note that there is no need of std::. The functions begin and end are required to be defined – Shooter Dec 14 '14 at 04:04
  • @Shooter good point, and actually the standard says: "begin-expression and end-expression are begin(__range) and end(__range), respectively, where the begin() and end() functions are looked up using the argument-dependent lookup (ADL) **which also includes the std namespace**." It includes the `std` namespace probably because `std::begin` and `std::end` are defined for regular C-style arrays. – vsoftco Dec 14 '14 at 22:01
2

std::begin() and std::end() won't work for pointers. They only work for arrays. If you want to deduce the size of your array you'll need to pass it as a reference your function:

#include <cstddef>
template <std::size_t A, std::size_t B>
void version_1(int (&arr)[B][A]) {
    for (const int (&p)[A] : arr) {
        for (int q : p) {
            cout << q << " ";
        }
        cout << '\n';
    }
}
Dietmar Kühl
  • 141,209
  • 12
  • 196
  • 356
1

Pointers are not the same as arrays. To be able to use range based for, your container must support std::begin and std::end. Standard C arrays can be used, but not pointers.

vsoftco
  • 52,188
  • 7
  • 109
  • 221