[英]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.