There are actually two issues. One is about how references work, and the other is about how templates work.
Let's examine them separately.
Consider these non-template functions:
void foo(int*&) {}
void bar(int* const &) {}
void baz(int*) {}
The second and third functions accept array arguments, but the first one does not. That's because arrays decay to temporary pointers. Non-const references don't bind to temporaries, but const references work just fine. The third function works just fine too because a temporary can be passed by value.
Now consider templates. If we turn the above functions into templates, only the third function works, the first two do not. Why is that?
That's because T*
does not match int[5]
, so deduction fails in the first two cases. It does not fail in the third case because there is a special provision for it in the standard.
If P is not a reference type:
- If A is an array type, the pointer type produced by the array-to-pointer standard conversion is used in place of A for type deduction; ...
So when the parameter type is T*
(not a reference), int[5]
is replaced with int*
, and lo and behold,T*
matches int*
, so T
can be deduced. But when the parameter is a reference, no such replacement is made.