带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
相关产品推荐
相关产品推荐

