交换优先级队列时尝试引用已删除的函数错误

Attempting to reference a deleted function error when swapping priority queues

本文关键字:删除 函数 错误 引用 优先级 队列 交换      更新时间:2023-10-16

我只是试图在两个优先级队列之间交换数据,并收到此错误。我也做了一些谷歌搜索,仍然不知道这里出了什么问题。

#include <queue>
class Node
{
public:
    int idx;
};
auto greater = []( const Node& a, const Node&  b) {return a.idx > b.idx; };
using QUEUE  = std::priority_queue<Node, std::vector<Node>, decltype(greater)>;
void foo(QUEUE& a)
{
    QUEUE b(greater);
    a.swap(b);
}
int main()
{
}

以下是完整的错误消息:

错误 C2280 ' &<< lambda_07efac20ebfa61cc8bb35aebd7d81f7c>>::运算符 =(常量 << lambda_07efac20ebfa61cc8bb35aebd7d81f7c>> &(':尝试引用 已删除的函数

Lambda 没有赋值运算符,swap(( 使用赋值。它将尝试对队列中持有的较大 lambda 使用赋值。

> 在 stdlibc++(很可能是 Visual Studio 的标准库(中实现std::swap使用老式的赋值:

swap(_Tp& __a, _Tp& __b)
{
    // concept requirements
    __glibcxx_function_requires(_SGIAssignableConcept<_Tp>)
    _Tp __tmp = __a;
    __a = __b;
    __b = __tmp;
}

相反,libcxx 使用 std::move 实现它:

swap(_Tp& __x, _Tp& __y) _NOEXCEPT_(is_nothrow_move_constructible<_Tp>::value &&
                                    is_nothrow_move_assignable<_Tp>::value)
{
     _Tp __t(_VSTD::move(__x));
     __x = _VSTD::move(__y);
     __y = _VSTD::move(__t);
}

为了交换类型std::priority_queue的对象,您必须交换它们的比较器,这些比较器在代码中表示为 lambda。由于删除了复制赋值运算符,因此无法在 stdlibc++ 中交换 lambda。

顺便说一下,没有必要使用 lambda,因为您的捕获列表是空的。一个简单的函数就可以完成这项工作。

bool greater(const Node& a, const Node&  b) {return a.idx > b.idx;};
using QUEUE = std::priority_queue<Node, std::vector<Node>, decltype(&greater)>;
void foo(QUEUE&& a)
{
    QUEUE b(&greater);
    a.swap(b);
}

或者,您可以将 lambda 替换为具有移动分配的可调用对象。