I know that one can determine the size of a C-style array (allocated on stack) using
template <typename T, size_t N>
size_t arr_size(T(&)[N])
{
    return N;
}
This works fine. Now my question is why do we have to pass the array by reference? If we pass it by value,
template <typename T, size_t N>
size_t arr_size(T[N])
{
    return N;
}
the code does not compile, i.e. in
#include <iostream>
template <typename T, size_t N>
size_t arr_size(T[N])
{
    return N;
}
int main()
{
    int arr[10];
    std::cout << "Array has size: " << arr_size(arr) << std::endl;
}
we get 
error: no matching function for call to 'arr_size'
    std::cout << "Array has size: " << arr_size(arr) << std::endl;
                                       ^~~~~~~~
/Users/vlad/minimal.cpp:6:8: note: candidate template ignored: couldn't infer template argument 'N'
size_t arr_size(T[N])
If we define
template <typename T, size_t N>
size_t arr_size(T(&)[N]) 
then it works.
