【问题标题】:Why do I need pass a comparator to construct a priority_queue when it is a lambda, but not when it is std::greater?为什么当它是 lambda 时我需要传递一个比较器来构造一个 priority_queue,而不是当它是 std::greater 时?
【发布时间】:2018-06-04 06:28:41
【问题描述】:

我正在阅读来自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);

}

不知道为什么q2不需要初始化? IE。而不是拥有

std::priority_queue&lt;int, std::vector&lt;int&gt;, std::greater&lt;int&gt; &gt; q2;

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

std::priority_queue&lt;int, std::vector&lt;int&gt;, std::greater&lt;int&gt; &gt; q2(std::greater&lt;int&gt;());

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

【问题讨论】:

    标签: c++ c++11 stl priority-queue function-object


    【解决方案1】:

    主要区别在于 std::greater 是默认可构造的,但闭包类型 (lambdas) 不是。

    因此,需要为队列提供一个 lambda 对象,以将其比较器作为构造函数参数复制构造。

    【讨论】:

      【解决方案2】:

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

      在这两种情况下,您都有一个“自定义比较功能”。 std::greater&lt;int&gt;decltype(cmp)&gt; 都命名了函数对象的类型。它们之间的区别在于 std::greater&lt;int&gt; 是默认可构造的,而 lambda 的类型永远不会。所以在初始化优先级队列的时候,this constructor...

      explicit priority_queue( const Compare& compare = Compare(),
                               Container&& cont = Container() );
      

      ... 将(概念上)愉快地默认初始化std::greater&lt;int&gt;(),但会在decltype(cmp)() 上失败。因此,您需要提供后者以进行显式复制。

      【讨论】:

        【解决方案3】:

        这是您的案例中使用的构造函数

        explicit priority_queue( const Compare& compare = Compare(),
                             Container&& cont = Container() );
        

        因此,如果您不传递任何参数,则模板类的默认构造函数将被调用。但是decltype(cmp) 不是默认可构造的。 lambda 闭包类型已删除默认构造函数。所以你需要明确提及cmp()

        在 C++20 中,我们将恢复这些默认构造函数。 lambdas

        【讨论】:

          猜你喜欢
          • 2018-09-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-11-02
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多