5

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

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

而不是 a std::vector,我想将值输入 a std::priority_queue。而不是返回.front()值,我想基于自定义比较函数.get().top()值。priority_queue假设这个自定义比较被计算为 value 和 instance 之间的绝对差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)。

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

4

3 回答 3

5

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

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>

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

如果您不想要任何性能缺陷,您也可以将比较器设为 astruct或其他东西并使用它来代替。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;
};
于 2018-12-13T17:32:02.557 回答
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;

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

std::priority_queue<
        int,
        std::vector<int>,
        std::function<bool(int,int)>> m_priority;

然后将 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 ); 
    } )
 {
 }

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

于 2018-12-13T17:48:55.863 回答
2

如果您要更改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);
    }
于 2018-12-13T18:53:24.237 回答