template <typename T>
T maxn(T arr[], int arrSize);
Это - общая форма шаблона функции. Если тебе нужно сделать явную специализацию шаблона, твоя явная специализация должна соответствовать этому общему шаблону.
template <>
const char* maxn(const char* arr[], int arrSize);
Сырые однобайтовые строки в C++ (при соблюдении
правила нуль-терминации) определяются типом
char*
или
const char*
если строку не планируется модифицировать. Наша функция не планирует модифицировать строки, следовательно явная специализация шаблона должна работать с типом
const char*
.
Тип
const char*
должен быть подставлен везде вместо параметра шаблона
T
.
Таким образом явная специализация шаблона для сырых строк будет полностью соответствовать общему шаблону функции.
А теперь немного о твоей ошибке.
template <> char* maxn(const char *arr[], int arrSize);
Это объявление не является явной специализацией приведенного выше шаблона. Это - определение перегрузки функции через явную специализацию какого-то иного неописанного шаблона. Это потому что результат функции
char*
отличен от параметра функции
const char*
.
В целом, эта запись является плохо сформулированной (ill-formed) по целому ряду причин, включая и то, что перегрузка не может осуществляться через изменение типа результата функции.
В целях обучения я советую не опускать перечисление аргументов явной специализации шаблона:
template <>
const char* maxn<const char*>(const char* arr[], int arrSize);
Благодаря этому простому шагу ты сообщишь компилятору больше информации о том, что ты хочешь сказать своим кодом и он тебя лучше поймет. В результате компилятор сможет поправить тебя там, где ты ошибся при описании явной специализации.