为什么我需要传递一个比较器来构造一个priority_queue,当它是一个lambda时,而不是当它是std :: greater时?

Sea*_*ean 2 c++ stl priority-queue function-object c++11

我正在从cppreference中读取代码示例:

#include <functional>
#include <queue>
#include <vector>
#include <iostream>

template<typename T> void print_queue(T& q) {
    while(!q.empty()) {
        std::cout << q.top() << " ";
        q.pop();
    }
    std::cout << '\n';
}

int main() {
    std::priority_queue<int> q;

    for(int n : {1,8,5,6,3,4,0,9,7,2})
        q.push(n);

    print_queue(q);

    std::priority_queue<int, std::vector<int>, std::greater<int> > q2;

    for(int n : {1,8,5,6,3,4,0,9,7,2})
        q2.push(n);

    print_queue(q2);

    // Using lambda to compare elements.
    auto cmp = [](int left, int right) { return (left ^ 1) < (right ^ 1);};
    std::priority_queue<int, std::vector<int>, decltype(cmp)> q3(cmp);

    for(int n : {1,8,5,6,3,4,0,9,7,2})
        q3.push(n);

    print_queue(q3);

}
Run Code Online (Sandbox Code Playgroud)

我不确定为什么q2不需要初始化?即没有

std::priority_queue<int, std::vector<int>, std::greater<int> > q2;

在原始代码中,我想我们应该有类似的东西

std::priority_queue<int, std::vector<int>, std::greater<int> > q2(std::greater<int>());

那么为什么当我们有一个自定义的比较函数时,我们可以在代码示例中省略初始化器q2而不是它q3

Bau*_*gen 10

关键区别在于std::greater默认可构造,但闭包类型(lambdas)不是.

因此,队列需要被赋予一个lambda对象来复制构造它的比较器作为构造函数参数.


Sto*_*ica 6

那么为什么当我们有一个自定义的比较函数时,我们可以省略q2的初始化器,但不能省略代码示例中的q3

在这两种情况下,您都有"自定义比较功能".无论std::greater<int>decltype(cmp)>名称的函数对象的类型.它们之间的区别在于std::greater<int>默认是可构造的,而lambda的类型永远不会.所以在初始化优先级队列时,这个构造函数 ......

explicit priority_queue( const Compare& compare = Compare(),
                         Container&& cont = Container() );
Run Code Online (Sandbox Code Playgroud)

...(概念上)会愉快地默认初始化std::greater<int>()但会失败decltype(cmp)().因此,您需要提供后者以明确复制.