簡體   English   中英

關於比較器的C ++模板問題

[英]C++ templating question regarding comparators

可能是一個非常新的C ++問題。 假設我有一個類,頂點,有幾個屬性和方法。 我想把一堆頂點填充到一個隊列中,並讓它們按頂點類的特殊屬性排序(為學校做一個基本的Dijkstra圖算法)。

但是,我遇到了一些滲透C ++語法的問題。 這是我的代碼(頂點未顯示,但它非常簡單)。

typedef std::priority_queue<benchmark::vertex*, 
                    std::vector<benchmark::vertex*>, 
                    std::less<benchmark::vertex*> > q_type;
q_type* q = new q_type();
benchmark::vertex* v1 = new benchmark::vertex(0.1,0.1);
v1->cost = 4;
benchmark::vertex* v2 = new benchmark::vertex(0.1,0.1);
v2->cost = 8;
benchmark::vertex* v3 = new benchmark::vertex(0.1,0.1);
v3->cost = 6;
benchmark::vertex* v4 = new benchmark::vertex(0.1,0.1);
v4->cost = 10;
benchmark::vertex* v5 = new benchmark::vertex(0.1,0.1);
v5->cost = 2;
q->push(v1);
q->push(v2);
q->push(v3);
q->push(v4);
q->push(v5);
while (!q->empty()) {
    std::cout << (*(q->top())).cost << std::endl;
    q->pop();
}

這在我的本地機器上輸出2,10,6,8,4。 我正在使用GCC(gcc版本4.3.3(Ubuntu 4.3.3-5ubuntu4))的Linux機器上測試它。 顯然,我希望它按順序吐出數字。

我如何制作比較器,以便在進行比較時查看並比較vertex.cost?

用任何帶有兩個頂點指針作為參數的函數或函子替換std::less<benchmark::vertex*> ,如果第一個參數屬於第二個參數,則返回true

std::less<benchmark::vertex*>將比較兩個指針,因此您看到的結果顯示了它們在內存中的順序。

std::less<benchmark::vertex*>比較地址而不是頂點

// Functor
struct VertexLess
{
   bool operator (const benchmark::vertex* left, const benchmark::vertex* right) const {
      return left->id < right->id;
   }
};

typedef std::priority_queue<benchmark::vertex*,     
                    std::vector<benchmark::vertex*>,
                    VertexLess > q_type;

Alexey Malistov回答的額外模板版本:

template <class T, class M, const M T::*member>
struct MemberGenericDereferenceLess
{
    bool operator()(const T* lhs, const T* rhs) const
    {
        return ((*lhs).*member < (*rhs).*member);
    }
};

typedef std::priority_queue<benchmark::vertex*,
                            std::vector<benchmark::vertex*>,
                            MemberGenericDereferenceLess<benchmark::vertex,
                                                         int,
                                                         &benchmark::vertex::cost> > q_type;

我曾經想過你只需要第一個和第三個模板參數,但我無法通過幾分鍾的黑客攻擊來推斷出class M (為讀者鍛煉)

這樣做的好處是您可以快速更改您排序的成員。 假設你的vertex看起來像......

namespace benchmark
{
    struct vertex
    {
        vertex(double a_, double b_) : a(a_), b(b_) {}

        double a;
        double b;

        int cost;
    };
}

您可以在aba typedef排序:

typedef std::priority_queue<benchmark::vertex*,
                            std::vector<benchmark::vertex*>,
                            MemberGenericDereferenceLess<benchmark::vertex,
                                                   double,
                                                   &benchmark::vertex::a> > q_type;

typedef std::priority_queue<benchmark::vertex*,
                            std::vector<benchmark::vertex*>,
                            MemberGenericDereferenceLess<benchmark::vertex,
                                                   double,
                                                   &benchmark::vertex::b> > q_type;

這是一個可以玩的小驅動程序:

#include <iostream>
#include <queue>
#include <vector>

namespace benchmark
{
    struct vertex
    {
        vertex(double a_, double b_) : a(a_), b(b_) {}

        double a;
        double b;

        int cost;
    };
}

template <class T, class M, const M T::*member>
struct MemberGenericDereferenceLess
{
    bool operator()(const T* lhs, const T* rhs) const
    {
        return ((*lhs).*member < (*rhs).*member);
    }
};

int main(int argc, char** argv)
{
    typedef std::priority_queue<benchmark::vertex*,
                                std::vector<benchmark::vertex*>,
                                MemberGenericDereferenceLess<benchmark::vertex,
                                                       int,
                                                       &benchmark::vertex::cost> > q_type;
    q_type q;

    benchmark::vertex* v1 = new benchmark::vertex(0.1,0.1);
    v1->cost = 4;
    benchmark::vertex* v2 = new benchmark::vertex(0.1,0.1);
    v2->cost = 8;
    benchmark::vertex* v3 = new benchmark::vertex(0.1,0.1);
    v3->cost = 6;
    benchmark::vertex* v4 = new benchmark::vertex(0.1,0.1);
    v4->cost = 10;
    benchmark::vertex* v5 = new benchmark::vertex(0.1,0.1);
    v5->cost = 2;
    q.push(v1);
    q.push(v2);
    q.push(v3);
    q.push(v4);
    q.push(v5);
    while(q.empty() == false)
    {
        std::cout << q.top()->cost << std::endl;
        q.pop();
    }

    // Clean up all of those new()s
    delete v1;
    delete v2;
    delete v3;
    delete v4;
    delete v5;

    std::cin.get();

    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM