How does std::end know the end of an array? How does std::end know the end of an array? arrays arrays

How does std::end know the end of an array?


But, how does it know the end of an array

It uses a template non-type parameter to deduce the size of the array, which can then be used to produce the end pointer. The C++11 signature from the cppreference section for std::end is as follows:

template< class T, std::size_t N >T* end( T (&array)[N] );

As hvd notes, since it is passed by reference this prevents decay to a pointer.

The implementation would be something similar to:

template< class T, std::size_t N >T* end( T (&array)[N] ){    return array + N ;}

Is the constant integer 5 will be stored some where?

5 or N is part of the type of the array and so N is available at compile time. For example applying sizeof to an array will give us the total number of bytes in the array.

Many times we see an array passed by value to a function. In that case, the array decays to a pointer to type stored in the array. So now the size information is lost. Passing by reference allows us to avoid this loss of information and extract the size N from the type.


is the constant integer 5 will be stored some where?

Yes, it's part of the type of the array. But no, it's not stored anywhere explicitly. When you have

int i[5] = { };

the type of i is int[5]. Shafik's answer talks about how this length is used to implement end.

If you've C++11, using constexpr would be the simple way to go

template <typename T, size_t N>inline constexpr size_tarrLen(const T (&arr) [N]) {    return N;}

If you've a pre-C++11 compiler where constexpr isn't available, the above function may not be evaluated at compile-time. So in such situations, you may use this:

template <typename T, size_t N>char (&arrLenFn(const T (&arr) [N]))[N];#define arrLen(arr) sizeof(arrLenFn(arr))

First we declare a function returning a reference to an array of N chars i.e. sizeof this function would now be the length of the array. Then we've a macro to wrap it, so that it's readable at the caller's end.

Note: Two arrays of the same base type but with different lengths are still two completely different types. int[3] is not the same as int[2]. Array decay, however, would get you an int* in both cases. Read How do I use arrays in C++? if you want to know more.


Because you are passing an array to std::end, and an array has type T [N]. std::end can tell when the array ends by looking at the N in the type.