Проблема использования шаблонного предиката в алгоритмах STL - PullRequest
4 голосов
/ 21 июня 2010

У меня есть следующий фрагмент кода, который выдает ошибку в первой форме использования 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 ]

3 голосов
/ 21 июня 2010

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

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

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

2 голосов
/ 21 июня 2010

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

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

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

...