如何在std :: sort和std :: priority_queue

时间:2019-06-18 09:02:44

标签: c++ templates stl

我正在尝试找出为std::sortstd::priority_queue不同定义自定义比较功能的原因。

例如, 对于std::sort,我可以执行以下操作:

bool compare(const vector<int>& a, const vector<int>& b)
{
    return a[0] < b[0];
}
class foo
{
public:
    vector<vector<int>> f(vector<vector<int>> list)
    {
        std::sort(list.begin(), list.end(), compare);
        return list;
    }
};


int main()
{
    vector<vector<int>> t = { {2,1},{1,0},{3,7} };
    foo n;

    auto ans = n.f(t);
    for (vector<int> x : ans)
    {
        printf("x[0]: %d , x[1]: %d \n", x[0], x[1]);
    }
    return 0;
}

运行代码后,结果为:

x [0]:1,x [1]:0

x [0]:2,x [1]:1

x [0]:3,x [1]:7

但是,如果我像这样在foo中定义另一个函数:

vector<vector<int>> f1(vector<vector<int>> list)
{
    std::priority_queue<vector<int>, vector<vector<int>>, compare> pq;
}

编译器不允许我这样做。解决这个问题的简单方法是在类内部创建一个结构,如下所示:

struct Compare
{
    bool operator()(const vector<int>& a, const vector<int>& b)
    {
        return a[0] < b[0];
    }
};

这是我到目前为止所拥有的: std::sort从en.cppreference.com传递比较函数对象,但priority_queue传递比较类型。我认为这可能就是为什么我不能对优先级队列使用相同的比较功能的原因。

另一个想法是,因为std::sort是一个函数,而priority_queue是一个容器,所以我们需要使其与众不同吗?

这就是我现在所拥有的。

对此我最担心的是为什么他们的行为方式如此不同? 造成这种差异的主要原因是什么?为什么我们需要与众不同?

p.s。任何人都有很好的书本建议,可以深入地解释STL,并且更专注于解释STL的代码以及为什么这样做?

1 个答案:

答案 0 :(得分:5)

您正在将compare指定为std::priority_queue的第三个模板参数,这不是正确的类型名称。您需要将其指定为函数指针类型(并将函数指针作为函数参数传递)。例如

std::priority_queue<vector<int>, vector<vector<int>>, decltype(compare)*> pq(compare);

std::priority_queue<vector<int>, vector<vector<int>>, bool (*)(const vector<int>&, const vector<int>&)> pq(compare);

std::sort是一个函数模板,因此当您可以将compare作为 function参数传递而 template参数可能是{{3 }}自动(作为函数指针类型); deduced是一个类模板,因此您必须显式指定 template参数,您只需要正确指定类型即可(如函数指针类型一样,如 std::sort的模板参数类型,该类型会自动推导)。

编辑

自C ++ 17起,我们有了std::priority_queue,那么您可以将其用作

vector<vector<int>> f1(vector<vector<int>> list)
{
    // deduced T=vector<int>, Container=vector<vector<int>>, Compare=bool (*)(const vector<int>&, const vector<int>&)
    std::priority_queue pq(compare, list);
    return ...
}

那么我们就不需要指定模板参数了。