我有以下代码,它在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;
}
答案 0 :(得分:3)
pred2是一个普通的函数模板,编译器需要使用特定类型对其进行实例化,该类型可以是现有类型或用户定义类型。
由于在第一次使用时,编译器无法从空规范推导出T参数。它会标记错误。
第二次使用时,它是正确的,正如你所指定的那样,编译器通过显式模板规范将T templete参数推断为int。
答案 1 :(得分:2)
如果我正确理解这些东西是如何工作的,那么问题是在前三种情况下你传递一个指向一个函数的指针,就其本质而言,它必须指向一个定义良好的函数重载,这不适用于第20行,因为你要指定一个整个类的函数(顺便说一下,每个函数必须由编译器在需要时显式生成)。类型推导规则在这里不适用,因为如果你传递一个函数指针,所有游戏都会在 {em} count_if
体之前被关闭(函数指针的类型必须是在count_if
模板实例化之前定义明确。)
在第21行,您确切地指定了您传递的函数,事实上编译器实例化了int类型的模板并将指针传递给该函数。
第22行正在发生一件完全不同的事情。您将定义良好的对象类型传递给count_if
。在count_if
的主体中,当调用operator()
时,编译器具有向其推导出模板参数的所有信息,因为它实际上是在调用它并且具有可以从中执行的实际参数类型扣除。