Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does the C++11 range-based for loop know the array size?

When I do something like this:

int my_array[5] = {1, 2, 3, 4, 5};
for (int &x : my_array) {
    x *= 2;
}

C++11 obviously knows that my array only has 5 elements. Is this information stored somewhere in the my_array object?

If so, is there any good reason why it is not made available to me as a developer (or is it?!?!?)? It seems that a lot of the world's problems would be solved if C++ devs always knew the bounds of the arrays they're dealing with.

like image 806
MrFox Avatar asked Nov 13 '12 20:11

MrFox


3 Answers

This is simply something that the language requires to work, and the compiler must implement. Obviously the complete type of my_array is int[5] (i.e. the size is part of the type), so this information is readily available.

Contrary to popular belief, there is no use of the free std::begin()/std::end() functions in play, although those would naively seem to be able to do the trick (but there's a catch involving ADL that would break this approach).

like image 131
Kerrek SB Avatar answered Nov 19 '22 02:11

Kerrek SB


It is available - you can define begin and end on arrays in standard C++. The size of the array is encoded in the type.

The general method is to use references to arrays.

Here's an example size function:

template<typename T, size_t N>
size_t array_size(T (& const)[N])
{
    return N;
}
like image 6
Pubby Avatar answered Nov 19 '22 00:11

Pubby


No, it's not part of the object. But it's part of the type. That's what the 5 in the array declaration is. However, this won't work:

void f(int arr[5]) {
    for(int& x: arr) {
        // whatever
    }
}

because the name of the array here decays into a pointer to its first element, that is, the argument declaration is equivalent to int *arr which has no size information.

like image 5
Pete Becker Avatar answered Nov 19 '22 02:11

Pete Becker