簡體   English   中英

無法對 priority_queue 中的對象進行排序<t>帶接口類型</t>

[英]Failing to sort objects in a priority_queue<T> with interface types

我有這個示例 C++ 代碼:

#include <iostream>
#include <string>
#include <memory>
#include <queue>
#include <algorithm>

class IA;
using spIA = std::shared_ptr<IA>;

class IA {
public:
    virtual auto PrintValue() const -> void = 0;
    virtual auto GetValue() const -> uint32_t = 0;
    virtual auto operator<(const spIA& other) const -> bool = 0;
    virtual ~IA() {}
};

class B : public IA {
protected:
    uint32_t m_a;
    uint32_t m_b; 
    uint32_t m_c;
public:
    B(uint32_t a, uint32_t b, uint32_t c)
    : m_a(a), m_b(b), m_c(c) {}

    virtual auto PrintValue() const -> void override {
        std::cout<<m_a<<" "<<m_b<<" "<<m_c<<"\n";
        return;
    }

    virtual auto GetValue() const -> uint32_t override {
        return m_a;
    }

    virtual auto operator<(const spIA& other) const -> bool override {
        // std::shared_ptr<B> bb = std::dynamic_pointer_cast<B>(other);
        return (GetValue() < other->GetValue());
    }
};

class C : public B {
public:
    C(uint32_t a, uint32_t b, uint32_t c) : B(a, b, c) {}

    virtual auto GetValue() const -> uint32_t override {
        return m_b;
    }

    virtual auto operator<(const spIA& other) const -> bool override {
        // std::shared_ptr<C> cc = std::dynamic_pointer_cast<C>(other);
        return GetValue() < other->GetValue();
    }
};

class D : public C {
public:
    D(uint32_t a, uint32_t b, uint32_t c) : C(a, b, c) {}

    virtual auto GetValue() const -> uint32_t override {
        return m_c;
    }

    virtual auto operator<(const spIA& other) const -> bool override {
        // std::shared_ptr<D> dd = std::dynamic_pointer_cast<D>(other);
        return GetValue() < other->GetValue();
    }
};

class IClassManager {
public:
    virtual auto SetValue(const std::vector<spIA>&) -> void = 0;
    virtual auto GetValue() -> void = 0;
    virtual ~IClassManager() {}
};

class ClassManagerB : public IClassManager {
protected:
    std::priority_queue<spIA> m_pqia;
public:
    virtual auto SetValue(const std::vector<spIA>& vspia) -> void override {
        for(auto &iter : vspia) {
            m_pqia.emplace(iter);
        }
        return;
    }
    virtual auto GetValue() -> void override {
        while(m_pqia.size()) {
            auto top = m_pqia.top();
            top->PrintValue();
            m_pqia.pop();
        }
    }
};

class ClassManagerC : public ClassManagerB {
};

class ClassManagerD : public ClassManagerB {
};

int main()
{
    std::vector<B> v_B = {
                {15, 7, 10},
                {2, 10, 15},
                {3, 1, 2}
            }; 

    std::vector<C> v_C = {
                {15, 7, 10},
                {2, 10, 15},
                {3, 1, 2}
            }; 

    std::vector<D> v_D = {
                {15, 7, 10},
                {2, 10, 15},
                {3, 1, 2}
            }; 

    std::vector<spIA> v_ib, v_ic, v_id;
    std::transform(v_B.begin(), v_B.end(), std::back_inserter(v_ib), [](auto &iter) { return std::make_shared<B>(iter); });
    std::transform(v_C.begin(), v_C.end(), std::back_inserter(v_ic), [](auto &iter) { return std::make_shared<C>(iter); });
    std::transform(v_D.begin(), v_D.end(), std::back_inserter(v_id), [](auto &iter) { return std::make_shared<D>(iter); });

    ClassManagerB cmb;
    cmb.SetValue(v_ib);
    cmb.GetValue(); // should sort by first field m_a
    std::cout<<"=======\n\n\n";

    ClassManagerC cmc;
    cmc.SetValue(v_ic);
    cmc.GetValue(); // should sort by second field m_b
    std::cout<<"=======\n\n\n";

    ClassManagerD cmd;
    cmd.SetValue(v_id);
    cmd.GetValue(); // should sort by third field m_c
    std::cout<<"=======\n\n\n";
}

我期望根據下面的具體類型對接口引用對象進行排序,但這並沒有發生。

預期 output:

3 1 2
2 10 15
15 7 10
=======


2 10 15
15 7 10
3 1 2
=======


2 10 15
15 7 10
3 1 2
=======

實際 Output:

3 1 2
2 10 15
15 7 10
=======


3 1 2
2 10 15
15 7 10
=======


3 1 2
2 10 15
15 7 10
=======

我究竟做錯了什么? 為什么我的 priority_queue 沒有基於operator<堆積?

priority_queue將對存儲在隊列中的類型使用std::less ,在您的情況下是spIA ,是std::shared_ptr<IA>的別名。 std::less在類型上調用operator< ,共享指針的比較將比較指針值,而不是指向的對象。

您需要為您的優先級隊列編寫自定義比較 object。 就像是:

auto cmp = [](const spIA &left, const spIA &right) { return *left < *right; }
priority_queue<spIA, std::vector<spIA>, decltype(cmp)> m_pqia(cmp);

std::priority_queue<spIA>的默認std::less<spIA> > 不會像您預期的那樣比較spIA指針。

您可以嘗試通過簡單地在class IA定義之后插入以下幾行代碼來為std::priority_queue<spIA>專門化std::less<spIA> ,這樣它就可以通過相應的覆蓋GetValue()正確比較spIA指針.

namespace std {
template<>
struct less<spIA>
{   
public:
    bool operator()(  const spIA& l,const spIA& r) const
    {        
        return (l->GetValue() < r->GetValue());
    }
};
}

另外我認為第一個預期的 output 應該是:

15 7 10
3 1 2
2 10 15
=======

如果按字段m_a排序。

暫無
暫無

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

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