How to write comparsion operator for custom type
The simple case
假設我們有一個類別
1 | struct Value { |
我們要怎麼寫出的程式碼
1 | Value v1, v2; |
有幾種方式
Naive solution
一種是當member function存在
手動寫出所有comparsion operator
1 | struct Value { |
另外一種是Free function存在
1 | bool operator<(const Value &lhs, const Value &rhs) { return lhs.v < rhs.v; } |
兩種實現原理相同,看情況選擇要用哪種,現在要討論的是其他的問題
當我們需要支持更多運算符號時,我們就需要寫更多的Function
1 | bool operator>(const Value &lhs, const Value &rhs); |
如果我們需要支援另外一種Type
1 | struct Value1 { |
然後又要出現一堆複製貼上加上手動修改的產物
1 | bool operator<(const Value1 &lhs, const Value1 &rhs); |
寫起來麻煩又沒什麼技術含量
CRTP solution
有些operator可以用其他operator表示,例如Not Equal就是Not + Equal
所以我們可以用CRTP技巧減少我們的程式碼
1 | template<class Derived> |
其他的operator可以如法炮製,很多的C++ Graphics/Math Library都用了這個技巧
只要實作<和==,可以用來推導出其他四種比較關係
不過很不直觀,CRTP就是一種Hack,那有沒有更好的方法
C++20 spaceship operator
Spaceship oerator也叫做The Three-Way Comparison Operator
這是C++20的一個特性,直接上Code來說明
1 |
|
而Compiler直接為你生成Comparsion Code,原先的程式碼視為這樣
1 | (a <=> b) < 0 //true if a < b |
這種方式類似於strcmp,會回傳<0,>0,0三種情形
基本上這樣就滿足了80%的需求了,不過人生最難的就是那個But
有需要的話自定義比較方式的話,可以自定義comparsion operator
1 | struct Value1 { |
不過現在spaceship operator必須回傳的是std::strong_ordering,std::weak_ordering,std::partial_ordering其中之一
至於三種ordering的差異,在此不探討,需要的話去Reference看,大部分只需要std::strong_ordering即能完成需求
Reference
- Spaceship Operator
- C++20: The Three-Way Comparison Operator
- Simplify Your Code With Rocket Science: C++20’s Spaceship Operator
- C++20 three-way comparison operator: Part 1
- C++20 three-way comparison operator: Part 2
- C++20 three-way comparison operator: Part 3
- C++20 three-way comparison operator: Part 4
- C++20 three way comparison operator: Part 5
- C++20 three way comparison operator: Part 6