C++ 在 priority_queue 中使用 std::greater() 并排序

cod*_*der 5 c++ templates types object c++11

为什么这两种情况的文档都说同样的事情,但它们以相反的方式声明,一个使用greater<int>而另一个使用greater<int>(). 有人可以解释一下吗?

文档priority_queue cpp 库说 comp

可以是用于对堆进行排序的比较对象。这可能是一个函数指针或函数对象

priority_queue<int, vector<int>, greater<int>> minheap;  //works
priority_queue<int, vector<int>, greater<int>() > minheap; //why fail?
Run Code Online (Sandbox Code Playgroud)

文档cpp 库 sort说了同样的事情,即 comp 可以是函数指针或函数对象。

sort (numbers.begin(), numbers.end(), std::greater<int>()); //works
sort (numbers.begin(), numbers.end(), std::greater<int>); //fail
Run Code Online (Sandbox Code Playgroud)

Vla*_*cow 6

在这份声明中

priority_queue<int, vector<int>, greater<int>> minheap; 
Run Code Online (Sandbox Code Playgroud)

greater<int>是一个模板参数,指定类型并对应于class Comparepriority_queue的类型模板参数

template<class T, class Container = vector<T>,
class Compare = less<typename Container::value_type>>
class priority_queue;
Run Code Online (Sandbox Code Playgroud)

在这份声明中

sort (numbers.begin(), numbers.end(), std::greater<int>());
Run Code Online (Sandbox Code Playgroud)

使用默认构造函数来创建类型的临时对象greater<int>

std::greater是一个模板结构

template<class T = void> struct greater;
Run Code Online (Sandbox Code Playgroud)

那就是它的专业化提供了一种类型。

您可以在声明中使用模板特化作为类型说明符。例如

std::greater<int> obj1;
std::greater<double> obj2;
std::greater<std::string> obj3;
Run Code Online (Sandbox Code Playgroud)

在第一种情况下,您必须为相应的类型模板形参指定类型实参。

在第二种情况下,您必须指定类型的对象greater<int>

请考虑到,如果您尝试使用记录std::greater<int>()作为priority_queue的模板参数,那么编译器会将其视为具有返回类型std::greater<int>且没有参数的函数类型说明符。因为编译器期望类型说明符作为模板参数而不是表达式。但是将这样的函数类型指定为类型模板参数对于priority_queue 来说没有意义。

为了使其更清楚,请按以下方式重写 std::sort 的调用

std::greater<int> obj;
sort (numbers.begin(), numbers.end(), obj );
Run Code Online (Sandbox Code Playgroud)

正如您在此处看到的那样,它是作为函数参数提供的std::greater<int>变量的类型说明符。上面的调用和这个调用的区别objstd::sort

sort (numbers.begin(), numbers.end(), std::greater<int>());
Run Code Online (Sandbox Code Playgroud)

是在最后一种情况下创建了一个std::greater<int>类似类型的临时对象std::greater<int>()

这是一个演示程序

#include <iostream>
#include <functional>
#include <iterator>
#include <algorithm>

int main() 
{
    int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

    for ( const auto &item : a ) std::cout << item << ' ';
    std::cout << '\n';

    std::greater<int> comp;

    //  Here is used an already created object of the type std::greater<int> 
    std::sort( std::begin( a ), std::end( a ), comp );

    for ( const auto &item : a ) std::cout << item << ' ';
    std::cout << '\n';

    //  Here is used a remporary object of the type std::less<int> 
    std::sort( std::begin( a ), std::end( a ), std::less<int>() );

    for ( const auto &item : a ) std::cout << item << ' ';
    std::cout << '\n';

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

程序输出是

0 1 2 3 4 5 6 7 8 9 
9 8 7 6 5 4 3 2 1 0 
0 1 2 3 4 5 6 7 8 9 
Run Code Online (Sandbox Code Playgroud)