C++如何提取shared_ptr<T>内部类型T适配priority_queue比较
编译错误核心原因
- 元素类型为
Priority时,std::greater<Priority>会直接调用类内实现的operator>,逻辑匹配所以可以正常编译运行,排序行为符合预期。 - 元素类型换成
shared_ptr<Priority>后,std::greater<shared_ptr<Priority>>的默认实现只会比较两个智能指针的存储地址,不会自动解引用调用Priority的比较逻辑;同时你没有为shared_ptr<Priority>实现对应的大于运算符重载,编译器找不到匹配的比较逻辑就会报错。
类型萃取适配方案实现
你猜测的通过类型萃取提取shared_ptr内部类型、自动解引用复用原有比较逻辑的思路完全可行,而且可以做到通用,不需要修改原Priority类,也不需要给priority_queue单独传入lambda或自定义比较函数。
实现方式是通过类型萃取识别shared_ptr类型,再特化标准库的std::greater对shared_ptr的比较逻辑,代码如下:
#include <memory> #include <queue> #include <vector> #include <functional> // 原Priority类保持完全不变,不需要做任何修改 class Priority { public: int priority; bool operator>(const Priority& other) const { return priority > other.priority; } }; // 类型萃取:提取shared_ptr包裹的内部类型 template<typename T> struct sptr_inner_type { using type = T; }; template<typename T> struct sptr_inner_type<std::shared_ptr<T>> { using type = T; }; // 特化std::greater针对shared_ptr的实现 namespace std { template<typename T> struct greater<std::shared_ptr<T>> { constexpr bool operator()(const std::shared_ptr<T>& lhs, const std::shared_ptr<T>& rhs) const { // 直接解引用,复用内部类型已实现的operator>逻辑 return *lhs > *rhs; } }; }
完成上述定义后,你原有的智能指针版本优先队列代码不需要任何调整即可正常运行,完全符合你的约束要求。
注意:你给出的示例代码中std::priority_queue<T, vector<T>, greater<T>>>末尾多写了一个右尖括号,实际使用时需要删除多余的符号,否则也会触发编译错误。
代理类方案可行性判断
你写的Sptr_Priority代理类方案完全可以正常工作:
- 这个类是对
shared_ptr<Priority>的薄封装,重载的operator>内部直接解引用调用了Priority的比较逻辑,std::greater<Sptr_Priority>可以正常匹配到这个重载,优先队列的排序逻辑是正确的。 - 重载的
operator->让你可以像使用原生shared_ptr<Priority>一样访问内部对象的成员,使用体验差异很小。 - 这个方案的局限性是只能针对
Priority类型生效,如果后续需要给其他存放在shared_ptr中的类型做同样的适配,需要重复编写代理类,通用性不如前面的类型萃取特化方案;如果你的业务场景只需要处理Priority这一种类型,这个写法没有任何问题。
内容的提问来源于stack exchange,提问作者f1msch
相关产品推荐
相关产品推荐

