在STL算法中使用模板化谓词的问题

4

我有以下代码片段,在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


7
为什么这种用法是不正确的?你希望听到什么?因为函数模板的语法就是这样设计的?还是因为函数模板参数推导只适用于调用时?请注意,template<typename T> struct pred4 { bool operator()(T&) {return true;} }; 会导致相同的问题。你需要将它作为 std::count_if(A, A + N, pred4<int>()) 传递进去。 - sbi
2个回答

3

pred2是一个普通的函数模板,编译器需要使用特定类型(可以是现有类型或用户定义类型)来实例化它。

由于在第一种用法中,编译器无法从空规范中推断出T参数。它会标记一个错误。

在第二种用法中,你已经明确指定了模板参数为int,因此编译器能够正确推断T模板参数。


2
如果我正确理解这些内容的工作原理,问题在于前三种情况下,您正在传递一个指向函数的指针,该函数由于其本质必须指向函数的明确定义重载,但不适用于第20行,因为您在那里指定了整个类的函数(顺便说一下,每次需要时编译器都必须明确生成这些函数)。类型推断规则在这里不适用,因为如果您传递函数指针,则所有游戏都会在评估count_if主体之前关闭(函数指针的类型必须在count_if模板实例化之前定义好)。

相反,在第21行,您正在指定要传递的确切函数,事实上编译器为int类型实例化模板并传递指向该函数的指针。

在第22行发生完全不同的事情。您正在将明确定义的对象类型传递给count_if。然后,在调用operator()时,当编译器调用它并具有真实参数以执行类型推断时,它有所有信息来对其进行模板参数推断。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接