В test1 компилятор создает шаблон с T [arraySize], являющимся его формой.Когда вы вызываете test1 (abc), вы предоставляете входной аргумент типа int [5], которому автоматически соответствует сопоставитель шаблонов.
Однако, если вы должны написать
int n=10;
int *abc = new int[n];
test1(abc);
test1<int,n>(abc);
, тогдакомпиляция не удалась бы, и компилятор заявил бы, что у него нет шаблона, соответствующего вызову функции test1 (abc) или вызову функции test1 (abc).
Это потому, что размер abc теперьдинамически распределяется, и поэтому тип abc является указателем, который имеет другой тип, и, следовательно, ни один шаблон не может быть сопоставлен с двумя вышеуказанными вызовами.
В следующем коде показаны некоторые типы
#include <iostream>
using namespace std;
template <class T> void printName() {cout<<typeid(T).name()<<endl;}
int main()
{
printName<int[2]>(); //type = A2_i
printName<int*>(); //type = Pi
getchar();
return 0;
}