C++具有 lambda 比较器错误的priority_queue

发布于 2024-11-03 12:42:23 字数 647 浏览 1 评论 0原文

我尝试在 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 是否有明显的问题,看起来有问题,而我可能会忽略?感谢您的阅读!

I have the following erroneous code which I am trying to compile in VC2010, but I'm getting the error C2974 this only occurs when I include the lambda expression, so I'm guessing it has something to do with that.

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;

I know the form of the template definition is correct as

priority_queue<int , vector<int>, greater<int>> pq;

Works as expected. Any ideas what I'm doing wrong? Is there something obviously wrong with the lambda that looks wrong that I might be overlooking? Thanks for reading!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

享受孤独 2024-11-10 12:42:23

首先定义 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 );

First define the lambda object, then pass it to the template's type using decltype and also pass it directly to the constructor.

auto comp = []( adjist a, adjlist b ) { return a.second > b.second; };
priority_queue< adjlist_edge , vector<adjlist_edge>, decltype( comp ) >
     adjlist_pq( comp );
小…红帽 2024-11-10 12:42:23

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; }
            } );

priority_queue takes the comparator as a template argument. Lambda functions are objects, and thus can't be used as template arguments (only very few types can be, among them integral types).

You can try using decltype there:

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; }
             } );

Failing that (and it will), you can use 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; }
            } );
甜警司 2024-11-10 12:42:23

接受的答案回答了如何使用 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 表达式的“假定现有的默认构造函数”。显然,它会失败。

关于您的问题:Compare 对象(lambda 或函数对象)是否具有默认构造函数会产生差异。

The accepted answer answered how to define a priority_queue with lambda expression as a custom Compare object.
I would address another aspect of the question: why it fails when define a pq in your way:

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;

Why we MUST pass the lambda as a parameter when constructing the priority queue? The reason lies in that lambda expression does not have a default constructor. So if you does not provide it when constructing the priority queue, the "supposed existing default constructor" of the lambda expression will be called. Clearly, it would fail.

With regard to your question: it is whether the Compare object(lambda or function object) has a default constructor makes the difference.

权谋诡计 2024-11-10 12:42:23

以下是使用优先级队列构建最小堆的示例。我使用 lambda 来定义比较器,给定由 vector定义的链表。 &列表

// 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);

Following is an example for building a minheap using priority queue. I have used a lambda to define the comparator, given linked lists defined by 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);
慈悲佛祖 2024-11-10 12:42:23

从 C++ 20 开始,没有捕获的 lambda 是默认可构造的,因此我们可以简单地将 lambda 包装在 decltype 中作为第三个模板参数,而根本不需要单独的变量。

priority_queue<adjlist_edge, vector<adjlist_edge>, 
  decltype([](adjlist_edge &a, adjlist_edge &b){return a.second > b.second;})> pq;

Since C++ 20, lambdas without captures are default constructible, so we can simply wrap the lambda in decltype as the third template parameter without requiring a separate variable at all.

priority_queue<adjlist_edge, vector<adjlist_edge>, 
  decltype([](adjlist_edge &a, adjlist_edge &b){return a.second > b.second;})> pq;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文