Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Range based for loop in function which passes an array as value [duplicate]

I'm learning C++ these days by myself and I have some problem understanding why this code doesn't compiles using #g++ -std=c++11 source.cpp. Actually it doesn't matter which specific standard I use, it just doesn't compiles.

#include <iostream>
#include <string>
using namespace std;
int print_a(char array[])
{
    for(char c : array)
        cout << c;
    cout << endl;
    return 0;
}
int main(void)
{
    char hello[] {"Hello!"};
    print_a(hello);
    return 0;
}

The error message:

debian@debian:~/Documents$ g++ -std=c++11 source.cpp
source.cpp: In function ‘int print_a(char*)’:
source.cpp:6:15: error: ‘begin’ was not declared in this scope
  for(char c : array)
               ^
source.cpp:6:15: note: suggested alternatives:
In file included from /usr/include/c++/4.9/bits/basic_string.h:42:0,
                 from /usr/include/c++/4.9/string:52,
                 from /usr/include/c++/4.9/bits/locale_classes.h:40,
                 from /usr/include/c++/4.9/bits/ios_base.h:41,
                 from /usr/include/c++/4.9/ios:42,
                 from /usr/include/c++/4.9/ostream:38,
                 from /usr/include/c++/4.9/iostream:39,
                 from source.cpp:1:
/usr/include/c++/4.9/initializer_list:89:5: note:   ‘std::begin’
     begin(initializer_list<_Tp> __ils) noexcept
     ^
/usr/include/c++/4.9/initializer_list:89:5: note:   ‘std::begin’
source.cpp:6:15: error: ‘end’ was not declared in this scope
  for(char c : array)
               ^
source.cpp:6:15: note: suggested alternatives:
In file included from /usr/include/c++/4.9/bits/basic_string.h:42:0,
                 from /usr/include/c++/4.9/string:52,
                 from /usr/include/c++/4.9/bits/locale_classes.h:40,
                 from /usr/include/c++/4.9/bits/ios_base.h:41,
                 from /usr/include/c++/4.9/ios:42,
                 from /usr/include/c++/4.9/ostream:38,
                 from /usr/include/c++/4.9/iostream:39,
                 from source.cpp:1:
/usr/include/c++/4.9/initializer_list:99:5: note:   ‘std::end’
     end(initializer_list<_Tp> __ils) noexcept
     ^
/usr/include/c++/4.9/initializer_list:99:5: note:   ‘std::end’
like image 377
Davycc Avatar asked Aug 05 '15 05:08

Davycc


2 Answers

The reason it doesn't compile is that in C++ a function parameter such as char array[] is adjusted to char* array. Your function really looks like

int print_a(char* array)
{
 ....
}

and the range based loops cannot deal with a pointer.

One solution is to pass the array by reference. C++ does not allow you to pass plain arrays by value. For example, this would accept an array of 5 chars:

int print_a(const char (& array)[5])
{
   for(char c : array) cout << c;
   cout << endl;
   return 42;
}

In order to generalise this to arrays of different sizes, you can use a template:

template <std::size_t N>
int print_a(const char (& array)[N])
{
   for(char c : array) cout << c;
   cout << endl;
   return 42;
}

Of course, there are easier ways to print a null-terminated string:

char hello[] {"Hello!"};
cout << hello << endl;

And there are standard library types that make passing string or char buffer objects around easier. For example, std::string, std::vector<char>, std::array<char, N> (where N is a compile time constant.)

like image 151
juanchopanza Avatar answered Mar 24 '23 21:03

juanchopanza


When you pass the array to the function, it "decays" to a pointer. As in the function really looks like this: int print_a(char *array) {...} The type of loop you are using, called a range loop, cannot handle pointers, which is the source of the error (trying to iterate over a pointer makes no sense).

Either you must pass the array by reference, or just use a regular for loop.

Honestly, if you are using C++ though, use C++. Use std::string, or std::vector.

like image 44
Iowa15 Avatar answered Mar 24 '23 21:03

Iowa15