You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

带lambda比较器的std::priority_queue调用std::swap:C++17编译失败C++20正常的原因

以Lambda为比较器的std::priority_queue交换问题:C17 vs C20

问题代码

以下代码尝试交换两个以无捕获Lambda为比较器的std::priority_queue对象,在C17下编译报错,但C20可正常编译:

#include <queue>

int main()
{
    auto cmp = [](int x, int y) {return x > y;};
    std::priority_queue<int, std::vector<int>, decltype(cmp)> pq1(cmp), pq2(cmp);
    std::swap(pq1, pq2); // 此行在C++17触发编译错误
    return 0;
}

C++17编译错误信息

error: object of type 'value_compare' (aka '(the lambda cmp)') cannot be assigned because its copy assignment operator is implicitly deleted
    {c = _VSTD::move(__q.c); comp = _VSTD::move(__q.comp); return *this;}

note: in instantiation of member function 'std::priority_queue<int, std::vector<int>, (lambda at main.cpp:13:16)>::operator=' requested here
  __x = _VSTD::move(__y);

note: in instantiation of function template specialization 'std::swap<std::priority_queue<int, std::vector<int>, (lambda at main.cpp:13:16)>>' requested here
    swap(pq1, pq2);

C++17编译失败的原因

在C++17及更早标准中,无捕获的Lambda类型虽然拥有合法的拷贝构造函数,但它的拷贝赋值运算符会被隐式删除。

std::swap对std::priority_queue的实现逻辑是通过移动赋值操作,完成两个队列内部数据(包括底层容器c和比较器comp)的交换。而priority_queue的移动赋值运算符需要将另一个队列的comp成员移动赋值给自己的comp,但Lambda的拷贝/移动赋值运算符被删除,导致这一步无法完成,最终触发编译错误。

C++20的关键变更

C++20标准对Lambda的特性进行了扩展:无捕获的Lambda类型会自动生成默认的拷贝赋值运算符和移动赋值运算符,同时还支持默认构造。

当Lambda拥有了合法的赋值运算符后,std::priority_queue的移动赋值就能顺利完成比较器的转移操作,std::swap也就可以正常编译并执行了。

内容的提问来源于stack exchange,提问作者Christopher Miller

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 12:55:15