为什么函数比较器不能像在排序中那样在优先级队列中工作?

Why function comparator doesn't work in priority queue like it does in sort?

We have a question, which discusses how to use a comparator in priority_queue in C++. He gives the overloaded operator class (or struct) as the third argument and it works fine. But bool function doesn't work. Why ? But it works fine in sort of the <algorithm>. When I looked into docs (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 将复制 比较类型 的对象。例如,这可能是 std::less<int>,其中该类型的对象是 std::less<int>(),被调用的是 std::less<int>()(x, y)。在 C++11 中,您可以使用 decltype,但在 C++03 中,"canonical" 方法是创建一个 "functor"(一个专门用作函数对象的完整类型。 ) 这就是 lambdas 被创建的原因之一。

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

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

std::sort有区别。 Sort 是一个函数,您可以让编译器 deduce 它是模板参数,这样您就不必显式指定它们。队列是一个 class 模板,无法推导出 class 模板的模板参数(至少在这种情况下不能)。

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

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

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