【问题标题】:Why function comparator doesn't work in priority queue like it does in sort?为什么函数比较器不像排序那样在优先级队列中工作?
【发布时间】:2016-04-23 09:35:46
【问题描述】:

我们有一个question,它讨论了如何在 C++ 中的priority_queue 中使用比较器。他将重载的operatorclass(或struct)作为第三个参数,它工作正常。但是bool 功能不起作用。为什么 ?但它在<algorithm>sort 中运行良好。当我查看文档 (priority_queue && algo/sort) 时,他们都将class Compare 作为可选的第三个参数。

#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <vector>

using namespace std;

bool cmp (const int &a,const int &b){ return a > b; }

struct cmp2
{
    bool operator() (const int &p1,const int &p2)
    {
        return p1 > p2;
    }
};

int main ()
{
//  freopen("test.txt","r",stdin);
    int a[10];
    vector<int> b(10);
    sort( a , a + 10, cmp );    // working cool
    sort( b.begin() , b.end() , cmp);   // working great
    priority_queue<int, vector<int> , cmp2 > x;    // as usual, working....
    priority_queue<int, vector<int> , cmp > y;   // not working why ?

    return 0;
}

错误:

A:\pqvsarray.cpp    In function 'int main()':
27  40  A:\pqvsarray.cpp    [Error] type/value mismatch at argument 3 in template parameter list for 'template<class _Tp, class _Sequence, class _Compare> class std::priority_queue'
27  40  A:\pqvsarray.cpp    [Error] expected a type, got 'cmp'
27  43  A:\pqvsarray.cpp    [Error] invalid type in declaration before ';' token

那么,为什么会有差异?

【问题讨论】:

  • 因为priority_queue模板需要一个类型,但是你给了它一个函数指针。
  • 那么,sort 如何/为什么要使用function pointer
  • @SelçukCihan 根据the priority_queue documentation,它可以是函数指针:这可以是函数指针或函数对象
  • @azam 因为在排序中,您实际上是在调用一个方法。但是,对于 priority_queue,您所做的是通过提供模板参数来指定您想要的优先级队列。这就是区别。

标签: c++ sorting stl compare priority-queue


【解决方案1】:

答案在于编译器错误。 优先级队列的第三个模板参数是比较器类型(如结构或类),而不是函数。

【讨论】:

  • 按照the priorty_queue documentation的说法,应该可以使用函数了。
  • @Aracthor:有可能。您只需要将正确的参数传递到正确的位置。您将函数指针的类型作为priority_queue 的模板参数传递,并将实际函数指针作为参数传递给构造函数。这与std::sort 的情况完全相同,除了在那里推断类型,您可以通过调用函数模板(如std::sort)来执行此操作,但不能通过类模板对象的实例化(如std::priority_queue)。
  • 如果你能解释一下“Why?”会更好。但是,谢谢!
【解决方案2】:

正如错误消息所暗示的,函数不能用作模板参数。 priority_queue 将复制 比较类型 的对象。例如,这可能是std::less&lt;int&gt;,其中该类型的对象是std::less&lt;int&gt;(),被调用的是std::less&lt;int&gt;()(x, y)。在 C++11 中,您可以使用 decltype,但在 C++03 中,“规范”方式是创建“函子”(专用于用作函数对象的整个类型。)这是其中一种创建lambdas 的原因。

【讨论】:

  • 很好,发现了 C++ 的不足并解释了在 C++11 中出现lambdas 的原因。
【解决方案3】:

您也可以使用带有std::priority_queue 的函数。您所做的不同之处在于您将函数作为函数参数传递给std::sort,但您尝试将函数定义为队列的模板参数。这显然不起作用,因为第三个参数是错误解释的类型参数。此外,您甚至不能有指针或引用模板参数。

如果你看一下reference,你会发现队列有一个用于传递比较对象的构造函数。 那是你必须传递函数的地方。

std::sort 有所不同。排序是一个函数,您可以让编译器deduce 它是模板参数,因此您不必显式指定它们。队列是一个类模板,类模板的模板参数不能推导(至少在这种情况下不是)。

模板参数默认为std::less&lt;typename Container::value_type&gt;,但您不想使用它。因此,您必须明确指定比较对象的类型。您在现在尝试传递对象的位置指定它。如何获取函数指针/引用的类型,你可能会问。你可以这样做:decltype(&amp;cmp)。如果您有一个不支持decltype 的过时编译器,那么您需要指定没有它的类型:bool (&amp;)(const int&amp;, const int&amp;)

这是一个示例,说明如何创建使用您的函数的队列。

std::priority_queue<int, std::vector<int>, decltype(&cmp)> x(cmp);

【讨论】:

  • 是的,bool (&amp;)(const int&amp;, const int&amp;) 因为第三个参数有效。如果我没记错的话,decltype 在 C++11 中。并且 +1 解释得很好。
  • 是的,decltype 确实是在 C++11 中添加的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-12
  • 1970-01-01
  • 1970-01-01
  • 2020-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多