Re: [问题] PriorityQueue 的 operator overload问题

楼主: poyenc (发箍)   2019-06-13 01:37:41
※ 引述《fatcat8127 (胖胖猫)》之铭言:
: 版上已经有很多大大们讨论关于 PriorityQueue Compare Function 的解决问题,
: 我将相关文章整理后再提出问题,以下说明仅凭我个人理解,不精确还请大大们指正。
: (1) priority_queue<int,vector<int>> PQ;
: 默认的 priority_queue 是 max_heap,假若想实现 min_heap 时可以搭配 greater<int>
: #include<functional>
: priority_queue<int,vector<int>,greater<int>> PQ;
: 参考这篇( https://pse.is/ECW72 ):overload greater function
: bool operator>(const struct_name &one,const struct_name &rhs){
: return one.dis>rhs.dis;
: }
: priority_queue<PAIR,vector<PAIR>,greater<vector<PAIR>::value_type>> PQ;
: (2) 自定义 function
: struct COMP{
: bool operator()(const PAIR &lhs,const PAIR &rhs){ return lhs.dis>rhs.dis; }
: };
: priority_queue<PAIR,vector<PAIR>,COMP> PQ;
: (3) 将定义方式写在 struct 内
: struct PAIR{
: int id; double dis;
: PAIR(int a=0,double b=0):id(a),dis(b){}
: // (1) overload operator "less than", but unable to overload "greater than"
: bool operator<(const PAIR &rhs)const{ return dis<rhs.dis; }
: };
: priority_queue<PAIR,vector<PAIR>> PQ;
: 上述是以ZJ-c942为例,用不同方式宣告使用 PriorityQueue。
: 附上程式码:https://ideone.com/lYQ8bo
: 我的问题:为何(3)将定义方式写在 strcut 内的这种方式,
: overload operator时 只能是">"不能是"<",虽然说相关的operator都可以从"<"转换
: 查了一下 StackOverflow,大部分都是谈论解决方法,但没有看到关于上述疑惑的说明
: 虽然有解决方案即可但还是希望有人可以解答这个无关痛痒的疑惑... 先谢谢大大们
简单说结论: 非不得已不要重载 operator<()
重载运算子应该被视为最后的解决方案, 为什么呢? 因为除了
assignment operator 以外, 其余的运算子都可以在类别本体以外
作宣告, 亦即: 即使不是类别作者也可以随意重载运算子. 如果你
确定想这么做, 以宣告的位置来分, 有 4 种情境需要注意:
namespace n1 {
struct meow {
(1)
bool operator<(const meow&) const;
};
(2)
bool operator<(const meow&, const meow&);
}
(3)
bool operator<(const n1::meow&, const n1::meow&);
namespace n2 {
(4)
bool operator<(const n1::meow&, const n1::meow&);
}
先不说无法明确表达语意这件事; 光是让呼叫能正常编译就困难重
重 (想想看为什么). 不过也因为这样高度的客制化弹性, 我们甚至
可以选择性地让编译器呼叫想要的运算子实作:
https://wandbox.org/permlink/mXhfObcCglfDxPdY
标准函式库里类似的例子有命名空间 std::rel_ops 和
std::string_literals. 把握 overload resolution 规则, 可以作
到改变 std::less<T> 的行为:
https://wandbox.org/permlink/0Fd5SrhjOPQ2LztO
因此开发/使用这类 function object 时有几点注意事项:
开发者
1. 不要依赖运算子造成语意不明, 用 Argument-dependent
lookup (ADL) 来找到类别作者所设计, 或者觉得合适的
函式呼叫
2. 如果非要依赖某些运算子, 尽量减少种类和参数组合
使用者
1. 不要假设底层的实作为何
2. 即使已经知道底层实作, 确保想要的函式有在编译器呼
叫候选名单里
最后还是建议原po自己写个类别作比较啦
作者: fatcat8127 (胖胖猫)   2019-06-14 18:50:00
感谢大神的解释

Links booklink

Contact Us: admin [ a t ] ucptt.com