如何将 priority_queue 与类实例的非静态比较方法一起使用?
Posted
技术标签:
【中文标题】如何将 priority_queue 与类实例的非静态比较方法一起使用?【英文标题】:How to use priority_queue with a non-static compare method of class instance? 【发布时间】:2018-12-13 17:17:09 【问题描述】:假设我有一个像这样的简单类:
class Test
public:
Test(int reference) m_reference = reference;
void feed(int x) m_data.push_back(x);
int get() return m_data.front();
private:
int m_reference;
std::vector<int> m_data;
;
我想将值输入std::priority_queue
,而不是std::vector
。我不想返回 .front()
值,而是想基于自定义比较函数 .get()
.top()
的 priority_queue
值。假设这个自定义比较被计算为一个值和实例reference
之间的绝对差。
我不知道如何在我的类属性中声明std::priority_queue
。
我试过了:
bool compare(int a, int b)
return std::abs(a - m_reference) < std::abs(b - m_reference);
然后:
std::priority_queue<int, std::vector<int>, decltype(&Test::compare)> m_priority;
我也尝试过像这样使用std::function
,但这会引发多个错误:
std::function<bool(int a, int b)>> pq([this](int a, int b)
return std::abs(a - m_reference) < std::abs(b - m_reference);
);
但这不起作用(请参阅Repl.it)。
你知道如何解决这个问题吗?
【问题讨论】:
@MatthieuBrucher 如果我添加static
,尽管reference
属性是非静态的,这仍然有效吗?
如何使用 lambda 并捕获要用于比较的实例?
@πάνταῥεῖ 我试过但无法捕获[this]
(因为我需要它用于m_reference
属性)。但是我对 lambda 函数没有太多经验,也许有一个解决方法。
@Delgan 你能在你的问题中展示你对 lambda 的尝试吗?也许我们可以解决你的问题。一般应该可以捕获this.
@πάνταῥεῖ priority_queue
声明使用 lambda 存在问题
【参考方案1】:
我设法通过使用:
std::function<bool(int,int)> comp = [this](int a, int b) return std::abs(a - m_reference) < std::abs(b - m_reference); ;
与
Test(int reference) : m_priority(comp) m_reference = reference;
和
std::priority_queue<int, std::vector<int>, decltype(comp)> m_priority;
您还需要#include <functional>
如果我正确理解您的问题,这就是您想要的吗?
如果您不希望出现任何性能缺陷,您也可以将比较器设为 struct
或其他东西,并使用它来代替 std::function
。
更新:
带有结构的版本看起来像这样(你可以传递一个this
指针而不是引用int
或者你喜欢它):
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
class Test
public:
Test(int reference) : m_priority(comp(m_reference)) m_reference = reference;
void feed(int x) m_data.push_back(x);
int get() return m_priority.top();
struct comp
int& reference;
comp(int& ref) : reference(ref)
bool operator()(int a, int b) return std::abs(a - reference) < std::abs(b - reference); ;
;
private:
int m_reference;
std::vector<int> m_data;
std::priority_queue<int, std::vector<int>, comp> m_priority;
;
【讨论】:
好吧,看来使用struct
的解决方案可能是最好的解决方案。感谢您的回答!【参考方案2】:
如果您可以使用 std::function
(它可能会有轻微的开销),它会起作用,但您尝试将 lambda 提交到类型声明中:
std::priority_queue<
int,
std::vector<int>,
std::function<bool(int,int)> comp = [this](int a, int b) return std::abs(a - m_reference) < std::abs(b - m_reference); > m_priority;
这行不通。您需要使用std::function
作为类型:
std::priority_queue<
int,
std::vector<int>,
std::function<bool(int,int)>> m_priority;
然后将 lambda 作为参数提交到m_priority
ctor:
Test(int reference) :
m_reference( reference ),
m_priority( [ref=reference]( int a, int b )
return std::abs( a - ref ) < std::abs( b - ref );
)
然后它会工作。 Live example
【讨论】:
【参考方案3】:如果您要更改 m_reference
的值,则需要重新排序 std::priority_queue
。下面是一种(可能)笨拙的方法,如果经常这样做和/或队列很大,这将非常昂贵,但它可以完成工作。该代码旨在作为@Slavas 答案的附加组件。
public:
void set_reference(int x)
m_reference = x;
sort();
private:
void sort()
std::priority_queue<int, std::vector<int>, std::function<bool(int,int)>> tmp(
[this](int a, int b) return std::abs(a - m_reference) < std::abs(b - m_reference);
);
while(m_priority.size())
tmp.emplace(std::move(m_priority.top()));
m_priority.pop();
std::swap(tmp, m_priority);
【讨论】:
以上是关于如何将 priority_queue 与类实例的非静态比较方法一起使用?的主要内容,如果未能解决你的问题,请参考以下文章