So to see how std::end works we can look at How does std::end know the end of an array? and see that the signature for std::end
is:
template< class T, std::size_t N >
T* end( T (&array)[N] );
and it is using template non-type parameter to deduce the size of the array and it is just a matter of pointer arithmetic to obtain the end:
return array + N ;
For std::begin
the signature is identical, with the exception of the name:
template< class T, std::size_t N >
T* begin( T (&array)[N] );
and calculating the beginning of the array is simply a matter of array to pointer decay which gives us a pointer to the first element of the array.
In C++14 these both become constexpr.