带有 lambda 比较器错误的 C++ priority_queue
Posted
技术标签:
【中文标题】带有 lambda 比较器错误的 C++ priority_queue【英文标题】:C++ priority_queue with lambda comparator error 【发布时间】:2011-08-14 01:04:16 【问题描述】:我尝试在 VC2010 中编译以下错误代码,但我收到错误 C2974 这仅在我包含 lambda 表达式时发生,所以我猜它与此有关.
typedef pair<pair<int, int>, int> adjlist_edge;
priority_queue< adjlist_edge , vector<adjlist_edge>,
[](adjlist_edge a, adjlist_edge b) -> bool
if(a.second > b.second) return true; else return false;
> adjlist_pq;
我知道模板定义的形式是正确的
priority_queue<int , vector<int>, greater<int>> pq;
按预期工作。任何想法我做错了什么?我可能忽略的看起来错误的 lambda 是否有明显错误?感谢阅读!
【问题讨论】:
***.com/questions/3867276/…的可能重复 【参考方案1】:首先定义 lambda 对象,然后使用 decltype
将其传递给模板的类型,并直接将其传递给构造函数。
auto comp = []( adjist a, adjlist b ) return a.second > b.second; ;
priority_queue< adjlist_edge , vector<adjlist_edge>, decltype( comp ) >
adjlist_pq( comp );
【讨论】:
谢谢,如果我必须单独声明它就可以了,你认为使用 lambda 对象而不是仿函数有什么好处吗? Re:默认构造函数:[expr.prim.lambda]/19 表示默认构造函数和复制赋值运算符被删除,复制构造函数和析构函数被隐式定义,用于闭包。 为什么还要直接传给构造函数? @Ari 因为 lambda 函数的类从来没有默认构造函数,即使它没有捕获。所以priority_queue
只能通过复制来构造比较函数对象。
他们是这个的现代化版本还是仍然是最新的?【参考方案2】:
priority_queue
将比较器作为模板参数。 Lambda 函数是对象,因此不能用作模板参数(只有极少数类型可以是整数类型)。
你可以在那里尝试使用decltype
:
priority_queue< adjlist_edge , vector<adjlist_edge>,
decltype( [](adjlist_edge a, adjlist_edge b) -> bool
if(a.second > b.second) return true; else return false;
)>
adjlist_pq( [](adjlist_edge a, adjlist_edge b) -> bool
if(a.second > b.second) return true; else return false;
);
如果失败(它会),您可以使用function<>
:
priority_queue< adjlist_edge , vector<adjlist_edge>,
function<bool(adjlist_edge,adjlist_edge)> >
adjlist_pq( [](adjlist_edge a, adjlist_edge b) -> bool
if(a.second > b.second) return true; else return false;
);
【讨论】:
+1 表示比 interjay 更接近,但这仍然行不通,因为每个 lambda 函数都有唯一的类型,即使是两个具有相同定义的对象。 函数更好,因为它不重复代码(显然,这是唯一正确的做法)。 @Alexandre:还有另一种选择,它牺牲了单线但比function
更干净。
您需要在priority_queue
中添加结束>
。由于 6 个字符,无法编辑。要求。【参考方案3】:
接受的答案回答了如何将带有 lambda 表达式的 priority_queue 定义为自定义 Compare 对象。 我将解决问题的另一个方面:为什么以您的方式定义 pq 时会失败:
typedef pair<pair<int, int>, int> adjlist_edge;
priority_queue< adjlist_edge , vector<adjlist_edge>,
[](adjlist_edge a, adjlist_edge b) -> bool
if(a.second > b.second) return true; else return false; > adjlist_pq;
为什么我们必须在构造优先级队列时将 lambda 作为参数传递?原因在于 lambda 表达式没有默认构造函数。所以如果你在构造优先级队列的时候没有提供它,就会调用lambda表达式的“假定存在的默认构造函数”。显然,它会失败。
关于您的问题:比较对象(lambda 或函数对象)是否具有默认构造函数会有所不同。
【讨论】:
【参考方案4】:以下是使用优先级队列构建 minheap 的示例。我使用了 lambda 来定义比较器,给定由 vector<ListNode *> &lists
定义的链表
// This comparator will be used to build minheap.
auto comp = [&](ListNode *a, ListNode *b)
return a->val > b->val;
;
// This priority queue is the min heap
priority_queue<ListNode *, vector<ListNode *>, decltype(comp)> pq(comp);
【讨论】:
以上是关于带有 lambda 比较器错误的 C++ priority_queue的主要内容,如果未能解决你的问题,请参考以下文章
带有非 const 字符串的 C++ lambda 到 std::function 错误