Проблема использования шаблонного предиката в алгоритмах STL

У меня есть следующий фрагмент кода, который выдает ошибку в первой форме использования pred2. Я надеялся, что кто-нибудь сможет объяснить, почему это конкретное использование некорректно, так как я думаю, что использование pred3 аналогично.

#include <algorithm>

bool pred1(const int&) { return true; }

template<typename T>
bool pred2(const T&) { return true; }

struct pred3
{
   template<typename T>
   bool operator()(T&) { return true; }
};

int main()
{
   int A[] = { 2, 0, 4, 6, 0, 3, 1, -7 };
   const int N = sizeof(A) / sizeof(int);

   std::count_if(A, A + N, &pred1);      //ok
   std::count_if(A, A + N, &pred2);      //error
   std::count_if(A, A + N, &pred2<int>); //ok
   std::count_if(A, A + N, pred3());     //ok
   return 0;
}

http://codepad.org/LRqY3Joq

2 ответа

pred2 - это обычный шаблон функции, и компилятор должен создать его экземпляр с использованием определенного типа, который может быть существующим типом или определяемым пользователем типом.

Поскольку при первом использовании компилятор не может вывести аргумент T из пустой спецификации. Это помечает ошибку.

При втором использовании это правильно, поскольку вы указали, какой компилятор выводит аргумент T templete в int через явную спецификацию шаблона.

Если я правильно понимаю, как все это работает, проблема в том, что в первых трех случаях вы передаете указатель на функцию, которая по самой своей природе должна указывать на четко определенную перегрузку функции, которая не применимо к строке 20, так как там вы указываете целый класс функций (каждая из которых, кстати, должна быть явно сгенерирована компилятором при необходимости). Правила вывода типов здесь не применяются, так как, если вы передадите указатель на функцию, все игры будут закрыты до count_if вычисляется тело (тип указателя функции должен быть четко определен до count_if создание шаблона).

Вместо этого в строке 21 вы указываете, какую именно функцию вы передаете, на самом деле компилятор создает экземпляр шаблона для типа int и передает указатель на эту функцию.

В строке 22 происходит совершенно другое. Вы передаете четко определенный тип объекта count_if, В теле count_if тогда, когда operator() При вызове компилятор имеет всю информацию для вывода аргумента шаблона, так как он фактически вызывает его и имеет реальные параметры, из которых он может выполнить вывод типа.

Другие вопросы по тегам