16.2.4. Указатели на функцию и дедукция аргумента
При инициализации или присвоении указателя на функцию (см. раздел 6.7) из шаблона функции для вывода аргументов шаблона компилятор использует тип указателя.
Предположим, например, что есть указатель на функцию, которая возвращает тип int и получает два параметра, каждый из которых является ссылкой на const int. Этот указатель можно использовать для указания на экземпляр функции compare():
template <typename Т> int compare(const T&, const T&);
// pf1 указывает на экземпляр int compare(const int&, const int&)
int (*pf1)(const int&, const int&) = compare;
Тип параметров pf1 определяет тип аргумента шаблона для параметра Т. Аргументом шаблона для параметра Т будет int. Указатель pf1 указывает на экземпляр функции compare() с параметром Т, связанным с типом int. Если аргументы шаблона не могут быть выведены из типа указателя функции, произойдет ошибка:
// перегруженные версии func(); каждая получает разный тип указателя
// функции
void func(int(*)(const string&, const string&));
void func(int(*)(const int&, const int&));
func(compare); // ошибка: какой из экземпляров compare?
Проблема в том, что, глядя на тип параметра функции func(), невозможно определить уникальный тип для аргумента шаблона. Вызов функции func() мог бы создать экземпляр версии функции compare(), получающей целые числа или версию, получающую строки. Поскольку невозможно идентифицировать уникальный экземпляр для аргумента функции func(), этот вызов не будет откомпилирован.
Неоднозначность вызова функции func() можно устранить при помощи явных аргументов шаблона:
// ok: явно определенная версия экземпляра compare()
func(compare<int>); // передача compare(const int&, const int&)
Это выражение вызывает версию функции func(), получающую указатель на функцию с двумя параметрами типа const int&.