如何在类实例的非静态比较方法中使用priority_queue?

Del*_*gan 5 c++ std priority-queue custom-compare c++11

假设我有一个像这样的简单类:

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;
};
Run Code Online (Sandbox Code Playgroud)

std::vector我想用值代替,而不是std::priority_queue。而不是返回的.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);
}
Run Code Online (Sandbox Code Playgroud)

然后:

std::priority_queue<int, std::vector<int>, decltype(&Test::compare)> m_priority;
Run Code Online (Sandbox Code Playgroud)

我也尝试过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);
});
Run Code Online (Sandbox Code Playgroud)

但这是行不通的(请参阅Repl.it)。

知道如何解决这个问题吗?

Rin*_*dov 5

我设法通过使用使其工作:

std::function<bool(int,int)> comp = [this](int a, int b) { return std::abs(a - m_reference) < std::abs(b - m_reference); };
Run Code Online (Sandbox Code Playgroud)

Test(int reference) : m_priority(comp) { m_reference = reference; }
Run Code Online (Sandbox Code Playgroud)

std::priority_queue<int, std::vector<int>, decltype(comp)> m_priority;
Run Code Online (Sandbox Code Playgroud)

您还需要 #include <functional>

如果我正确理解您的问题,这就是您想要的?

您也可以将比较器设置为a struct或其他东西,然后使用它,而不std::function希望出现任何性能缺陷。

更新:

带有struct的版本看起来像这样(您可以传递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;
};
Run Code Online (Sandbox Code Playgroud)


Sla*_*ica 5

如果您可以使用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;
Run Code Online (Sandbox Code Playgroud)

这是行不通的。您需要std::function用作类型:

std::priority_queue<
        int,
        std::vector<int>,
        std::function<bool(int,int)>> m_priority;
Run Code Online (Sandbox Code Playgroud)

然后将 lambdam_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 ); 
    } )
 {
 }
Run Code Online (Sandbox Code Playgroud)

那么它会起作用。活生生的例子