使用Lambda作为std::priority_queue比较函数时赋值报错的原因与解决
std::priority_queue赋值清空时的编译错误分析与解决
问题代码
#include <iostream> #include <queue> #include <vector> using std::cout; using std::priority_queue; using std::vector; int main() { const auto comp = [](int a, int b) { return a > b; }; auto a = priority_queue<int, vector<int>, decltype(comp)>(comp); a.push(10); a.push(9); a.push(8); // 3 cout << a.size() << '\n'; a = priority_queue<int, vector<int>, decltype(comp)>(comp); // 0 cout << a.size() << '\n'; return 0; }
编译错误信息
文件包含自tmp.cpp:1: /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/queue:455:39: 错误:无可行的重载'='运算符 {c = _VSTD::move(__q.c); comp = _VSTD::move(__q.comp); return *this;} ~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~ tmp.cpp:19:7: 注意:此处请求实例化成员函数'std::priority_queue<int, std::vector<int>, const (lambda at tmp.cpp:9:23)>::operator=' a = priority_queue<int, vector<int>, decltype(comp)>(comp); ^ tmp.cpp:9:23: 注意:候选函数(隐式复制赋值运算符)不可行:'this'参数类型为'std::priority_queue<int, std::vector<int>, const (lambda at tmp.cpp:9:23)>::value_compare'(别名'const (lambda at tmp.cpp:9:23)'),但方法未标记为const const auto comp = [](int a, int b) { ^ 生成1个错误。
报错原因
核心问题在于const auto comp的定义:
decltype(comp)推导的类型是带const限定的lambda类型,因此priority_queue的内部比较器成员类型为const lambda。std::priority_queue的默认赋值运算符会尝试对内部比较器执行comp = _VSTD::move(__q.comp)的赋值操作,但lambda的隐式复制/移动赋值运算符是非const成员函数,无法作用于const类型对象,导致编译器找不到可行的赋值运算符重载,触发报错。
解决方法
方法1:移除比较器的const修饰
将const auto comp改为auto comp,让decltype(comp)推导为普通lambda类型,支持移动赋值:
auto comp = [](int a, int b) { return a > b; };
修改后,priority_queue的赋值运算符可正常处理内部比较器的移动操作,编译通过。
方法2:使用swap操作清空队列
若必须保留const修饰的比较器,可通过swap临时队列的方式清空,避免触发赋值运算符:
priority_queue<int, vector<int>, decltype(comp)>(comp).swap(a);
swap仅交换两个队列的内部数据,不会对比较器执行赋值操作,可绕过const lambda无法赋值的限制。
方法3:使用默认构造临时对象(C++20及以上)
若编译器支持C++20,lambda支持默认构造,可直接构造无参临时队列完成清空:
a = decltype(a)();
内容的提问来源于stack exchange,提问作者Brian
相关产品推荐
相关产品推荐

