【问题标题】:Default constructed std::priority_queue with a lambda带有 lambda 的默认构造 std::priority_queue
【发布时间】:2021-10-04 07:31:21
【问题描述】:

我错误地在定义std::priority_queue 时省略了compare 参数:

#include <queue>

int main()
{
    constexpr auto cmp{[](int a, int b) { return a > b; }};
    std::priority_queue<int, std::vector<int>, decltype(cmp)> pq;
}

,它编译成功并且当我用它来实现Dijkstra的算法时工作正常。 然后我意识到我在构造pq时只传递了cmp的类型信息。

但是,只有在使用--std=c++20 标志时,代码才能编译。 我浏览了 cppreference.com 上的 priority_queue 引用,但找不到任何关于自 C++20 以来发生的更改的通知。

我使用了以下版本的g++:

g++ (Ubuntu 10.3.0-1ubuntu1~20.04) 10.3.0

这是自 C++20 以来的预期行为,如果是,是什么影响了这种变化?

【问题讨论】:

  • 从 C++20 开始,lambda 是默认可构造的。
  • *无捕获的 lambdas。

标签: c++ lambda constructor c++20 priority-queue


【解决方案1】:

更改发生在lambdas。

如果未指定捕获,则闭包类型具有默认的默认构造函数。否则,它没有默认构造函数(这包括存在默认捕获的情况,即使它实际上没有捕获任何东西)。 (C++20 起)

在C++20之前,lambda闭包类型不是DefaultConstructible,比较器对象不能在std::priority_queue的默认构造函数中默认构造,那么你必须传递lambda对象到std::priority_queue 的构造函数接受比较器对象。

constexpr auto cmp{[](int a, int b) { return a > b; }};
std::priority_queue<int, std::vector<int>, decltype(cmp)> pq(cmp);

【讨论】:

  • 这是否意味着特定的return a &gt; b;,但不是,例如return a &lt;= b,是从lambda类型签名本身隐含的?
  • @JayLee 签名无关紧要,你可以改变你想要的顺序,使用return a &gt; b;你会得到最小的元素top();使用return a &lt; b;,你会得到最大的元素top()。
  • 也许我应该改写我的问题:编译器如何仅从decltype(cmp) 构造cmp 本身?
  • 例如,我可以找出一个lambda的参数和返回类型:stackoverflow.com/questions/7943525/…,我可以看到编译器可以从表达式@中的(cmp)构造cmp 987654337@。但是cmp 的主体实际上是从decltype(cmp) 本身推导出来的吗?
  • @JayLee decltype(cmp) 给出 lambda 的类型,然后将其默认构造为比较器。它与this code 相同,除非编译器为您生成 lambda 闭包类型而不是用户定义的类型。
猜你喜欢
  • 1970-01-01
  • 2018-10-04
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多