Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

begin and end function for built-in array types

I'm trying to obtain a begin and one off the end pointer for a array of C-style strings (an array of pointers to char). Why can't I call the begin and end function in order to obtain them?

#include <iostream>
#include <iterator>

int main(int argc,char *argv[])
{
  char **first=std::begin(argv),**last=std::end(argv);
}

The compiler says that there's no matching function for my call to begin(char**&)

like image 491
Luca Avatar asked Mar 16 '23 00:03

Luca


2 Answers

The functions are applied to arrays. As for the parameter argv then it actually has type char ** because arrays passed by value are converted to pointers to their first elements and parameters are adjusted also to pointers.

You could write simply

#include <iostream>
#include <iterator>

int main(int argc,char *argv[])
{
   auto first = arg, last = argv + argc;
}

You could use the functions std::begin and std::end if your function declares the corresponding parameter as reference to array. For example

int MyMain( char * ( &argv )[10] )
{
   auto first = std::begin( argv ), last = std::end( argv );
}

Nevertheless it is the same if to write

   auto first = argv, last = argv + 10;

Here is how the functions are defined in the C++ Standard

template <class T, size_t N> T* begin(T (&array)[N]);
4 Returns: array.

template <class T, size_t N> T* end(T (&array)[N]);
5 Returns: array + N.
like image 126
Vlad from Moscow Avatar answered Mar 23 '23 08:03

Vlad from Moscow


The problem that the compiler faces, is that it has no way to guess the size of argv, because it is not an array but a mere pointer.

Arrays can always be used as pointers, because an array can decay to a pointer to its first element. But the inverse is false! You can access the elements of an array through the array or through a pointer exactly the same, but the pointer and the array are not the same:

int a[5];
int *p = a; // p[i] and a[i] are now the same
size_t s = sizeof(a); // s is 5 * sizeof(int) 20 on common (32 bits) architectures
size_t s2 = sizeof(p);  // s2 is just sizeof(int *) 4 on 32 bits architecture

The convention says that argv has argc elements (and that argv[argc] is a null pointer). But std::begin and std::end do not make use of that convention. So do it by hand as a nice programmer:

#include <iostream>
#include <iterator>

int main(int argc,char *argv[])
{
  char **first=argv,**last=argv + argc;
}
like image 22
Serge Ballesta Avatar answered Mar 23 '23 07:03

Serge Ballesta