【问题标题】:Problem using templated predicate in STL algorithms在 STL 算法中使用模板谓词的问题
【发布时间】:2010-06-21 09:37:03
【问题描述】:

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

【问题讨论】:

  • “为什么这个特定的用法不正确” 你想听什么? 因为函数模板的语法就是这样设计的? 因为函数模板参数推导只适用于调用?请注意,template&lt;typename T&gt; struct pred4 { bool operator()(T&amp;) {return true;} }; 会导致同样的问题。您必须将其传递为 std::count_if(A, A + N, pred4&lt;int&gt;());

标签: c++ templates stl compiler-errors predicate


【解决方案1】:

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

自从第一次使用以来,编译器无法从空规范中推断出 T 参数。它会标记一个错误。

第二种用法是正确的,正如您指定的那样,编译器通过显式模板规范将 T 模板参数推导出为 int。

【讨论】:

    【解决方案2】:

    如果我正确理解这些事情是如何工作的,那么问题是在前三种情况下,您传递的是一个指向函数的指针,就其本质而言,它必须指向一个定义明确的函数重载,这不适用于第 20 行,因为您在那里指定了一个 whole class 函数(顺便说一下,每个函数都必须在需要时由编译器显式生成)。类型推导规则在这里不适用,因为,如果你传递一个函数指针,所有游戏都会在count_if body 被评估之前关闭(函数指针的类型必须是正确的) - 在count_if 模板实例化之前定义)。

    相反,在第 21 行,您要准确指定要传递的函数,实际上编译器会实例化 int 类型的模板并将指针传递给该函数。

    在第 22 行,发生了完全不同的事情。您将一个定义明确的对象类型传递给count_if。在count_if 的主体中,当operator() 被调用时,编译器拥有所有信息来推断它的模板参数,因为它实际上是在调用它并且具有可以从中执行类型推断的真实参数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多