Skip to content

Commit

Permalink
optional : 三方比較演算子に対応 #900
Browse files Browse the repository at this point in the history
  • Loading branch information
faithandbrave committed Dec 9, 2022
1 parent 0936e99 commit b4577ca
Show file tree
Hide file tree
Showing 9 changed files with 223 additions and 71 deletions.
2 changes: 2 additions & 0 deletions GLOBAL_QUALIFY_LIST.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@
* years[link /reference/chrono/duration_aliases.md]
* <climits>[link /reference/climits.md]
* <compare>[link /reference/compare.md]
* compare_three_way_result_t[link /reference/compare/compare_three_way_result.md]
* strong_ordering[link /reference/compare/strong_ordering.md]
* three_way_comparable_with[link /reference/compare/three_way_comparable.md]
* <coroutine>[link /reference/coroutine.md]
* <cmath>[link /reference/cmath.md]
* <codecvt>[link /reference/codecvt.md]
Expand Down
1 change: 1 addition & 0 deletions reference/optional/optional.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ namespace std {
|------|------|----------------|
| [`operator==`](optional/op_equal.md) | 等値比較 | C++17 |
| [`operator!=`](optional/op_not_equal.md) | 非等値比較 | C++17 |
| [`operator<=>`](optional/op_compare_3way.md) | 三方比較 | C++17 |
| [`operator<`](optional/op_less.md) | 左辺が右辺より小さいかを判定する | C++17 |
| [`operator<=`](optional/op_less_equal.md) | 左辺が右辺以下かを判定する | C++17 |
| [`operator>`](optional/op_greater.md) | 左辺が右辺より大きいかを判定する | C++17 |
Expand Down
122 changes: 122 additions & 0 deletions reference/optional/optional/op_compare_3way.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# operator<=>
* optional[meta header]
* std[meta namespace]
* function template[meta id-type]
* cpp20[meta cpp]

```cpp
namespace std {
template <class T, three_way_comparable_with<T> U>
constexpr compare_three_way_result_t<T,U>
operator<=>(const optional<T>& x, const optional<U>& y); // (1) C++20

template <class T>
constexpr strong_ordering
operator<=>(const optional<T>&, nullopt_t) noexcept; // (2) C++20

template <class T, three_way_comparable_with<T> U>
constexpr compare_three_way_result_t<T,U>
operator<=>(const optional<T>& x, const U& y); // (3) C++20
}
```
* nullopt_t[link /reference/optional/nullopt_t.md]
## 概要
`optional`オブジェクトの三方比較を行う。
- (1) : `optional<T>`と`optional<U>`の三方比較
- (2) : `optional<T>`と無効値[`nullopt_t`](/reference/optional/nullopt_t.md)の三方比較
- (3) : `optional<T>`と有効値`U`の三方比較
## 戻り値
- (1) :
- `x && y`が`true`である場合`*x <=> *y`を返し、そうでなければ`bool(x) <=> bool(y)`を返す
- (2) :
```cpp
```return bool(x) <=> false;`
```

- (3) : 以下と等価
```cpp
return bool(x) ? *x <=> v : strong_ordering::less;
```


## 備考
- (2) : この演算子により、以下の演算子が使用可能になる (C++20):
- `bool operator<(const optional<T>&, const nullopt_t&) noexcept;`
- `bool operator<(const nullopt_t&, const optional<T>&) noexcept;`
- `bool operator<=(const optional<T>&, const nullopt_t&) noexcept;`
- `bool operator<=(const nullopt_t&, const optional<T>&) noexcept;`
- `bool operator>(const optional<T>&, const nullopt_t&) noexcept;`
- `bool operator>(const nullopt_t&, const optional<T>&) noexcept;`
- `bool operator>=(const optional<T>&, const nullopt_t&) noexcept;`
- `bool operator>=(const nullopt_t&, const optional<T>&) noexcept;`


## 例
```cpp example
#include <cassert>
#include <optional>

int main()
{
// optionalオブジェクト同士の比較
{
std::optional<int> a = 3;
std::optional<int> b = 1;
std::optional<int> c = 3;
std::optional<int> none;

assert((a <=> c) == 0);
assert((a <=> b) != 0);
assert((a <=> none) != 0);
assert((none <=> a) != 0);
}

// optionalオブジェクトとnulloptの比較
{
std::optional<int> p = 3;
std::optional<int> none;

assert((p <=> std::nullopt) != 0);
assert((none <=> std::nullopt) == 0);

assert((std::nullopt <=> p) != 0);
assert((std::nullopt <=> none) == 0);
}

// optionalオブジェクトと有効値の比較
{
std::optional<int> p = 3;
std::optional<int> none;

assert((p <=> 3) == 0);
assert((3 <=> p) == 0);

assert((none <=> 3) != 0);
assert((3 <=> none) != 0);
}
}
```
* std::nullopt[link /reference/optional/nullopt_t.md]

### 出力
```
```

## バージョン
### 言語
- C++20

### 処理系
- [Clang](/implementation.md#clang):
- [GCC](/implementation.md#gcc): 10
- [Visual C++](/implementation.md#visual_cpp): ??


## 参照
- [P1614R2 The Mothership has Landed](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1614r2.html)
- C++20での三方比較演算子の追加と、関連する演算子の自動導出
32 changes: 22 additions & 10 deletions reference/optional/optional/op_equal.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,20 @@
```cpp
namespace std {
template <class T, class U>
constexpr bool operator==(const optional<T>& x, const optional<U>& y); // (1)
constexpr bool operator==(const optional<T>& x, const optional<U>& y); // (1) C++17

template <class T>
constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept; // (2)
template <class T>
constexpr bool operator==(nullopt_t, const optional<T>& y) noexcept; // (3)
constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept; // (2) C++17

template <class T, class U>
constexpr bool operator==(const optional<T>& x, const U& y); // (4)
constexpr bool operator==(const optional<T>& x, const U& y); // (3) C++17

template <class T, class U>
constexpr bool operator==(const U& x, const optional<T>& y); // (5)
constexpr bool operator==(const T& x, const optional<U>& y); // (4) C++17

// (2) により、以下のオーバーロードが使用可能になる (C++20)
template <class T>
constexpr bool operator==(nullopt_t, const optional<T>& y) noexcept; // (5) C++17
}
```
* nullopt_t[link /reference/optional/nullopt_t.md]
Expand All @@ -27,15 +30,22 @@ namespace std {
## 要件
- (1), (4), (5) : 型`T`が`==`で比較可能であること
- (1), (3), (4) : 型`T`が`==`で比較可能であること
## 戻り値
- (1) : `x`と`y`がどちらも有効値を持っていれば、有効値同士を等値比較した結果を返す。`x`と`y`がどちらも有効値を持っていなければ`true`を返す。`x`と`y`のうち、どちらかが有効値を持ち、どちらかが持たない場合は`false`を返す
- (2) : `x`が有効値を持っていなければ`true`、そうでなければ`false`を返す
- (3) : `y`が有効値を持っていなければ`true`、そうでなければ`false`を返す
- (4) : `x`が有効値を持っていれば、`y`と等値比較した結果を返す。そうでなければ`false`を返す
- (5) : `y`が有効値を持っていれば、`x`と等値比較した結果を返す。そうでなければ`false`を返す
- (3) : `x`が有効値を持っていれば、`y`と等値比較した結果を返す。そうでなければ`false`を返す
- (4) : `y`が有効値を持っていれば、`x`と等値比較した結果を返す。そうでなければ`false`を返す
- (5) : `y`が有効値を持っていなければ`true`、そうでなければ`false`を返す
## 備考
- (2) : この演算子により、以下の演算子が使用可能になる (C++20):
- `bool operator==(const nullopt_t&, const optional<T>&) noexcept;`
- `bool operator!=(const optional<T>&, const nullopt_t&) noexcept;`
- `bool operator!=(const nullopt_t&, const optional<T>&) noexcept;`
## 例
Expand Down Expand Up @@ -102,3 +112,5 @@ int main()

## 参照
- [LWG Issue 2934. `optional<const T>` doesn't compare with `T`](https://wg21.cmeerw.net/lwg/issue2934)
- [P1614R2 The Mothership has Landed](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1614r2.html)
- C++20での三方比較演算子の追加と、関連する演算子の自動導出
29 changes: 16 additions & 13 deletions reference/optional/optional/op_greater.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,18 @@
```cpp
namespace std {
template <class T, class U>
constexpr bool operator>(const optional<T>& x, const optional<U>& y); // (1)

template <class T>
constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept; // (2)
template <class T>
constexpr bool operator>(nullopt_t, const optional<T>& y) noexcept; // (3)
constexpr bool operator>(const optional<T>& x, const optional<U>& y); // (1) C++17

template <class T, class U>
constexpr bool operator>(const optional<T>& x, const U& y); // (4)
constexpr bool operator>(const optional<T>& x, const U& y); // (2) C++17
template <class T, class U>
constexpr bool operator>(const U& x, const optional<T>& y); // (5)
constexpr bool operator>(const U& x, const optional<T>& y); // (3) C++17

// operator<=>により、以下のオーバーロードが使用可能になる (C++20)
template <class T>
constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept; // (4) C++17
template <class T>
constexpr bool operator>(nullopt_t, const optional<T>& y) noexcept; // (5) C++17
}
```
* nullopt_t[link /reference/optional/nullopt_t.md]
Expand All @@ -27,15 +28,15 @@ namespace std {
## 要件
- (1), (4), (5) : 型`T`と型`U`が`>`演算子で比較可能であること
- (1), (2), (3) : 型`T`と型`U`が`>`演算子で比較可能であること
## 戻り値
- (1) : `x`と`y`がどちらも有効値を持っていれば、有効値同士を`>`演算子で比較した結果を返す。`x`が有効値を持っていなければ`false`を返す。`y`が有効値を持っていなければ`true`を返す
- (2) : `x.`[`has_value()`](has_value.md)を返す
- (3) : `false`を返す
- (4) : `return x.`[`has_value()`](has_value.md) `? x.`[`value()`](value.md) `> y : false;`
- (5) : `return y.`[`has_value()`](has_value.md) `? x > y.`[`value()`](value.md) `: true;`
- (2) : `return x.`[`has_value()`](has_value.md) `? x.`[`value()`](value.md) `> y : false;`
- (3) : `return y.`[`has_value()`](has_value.md) `? x > y.`[`value()`](value.md) `: true;`
- (4) : `x.`[`has_value()`](has_value.md)を返す
- (5) : `false`を返す
## 例
Expand Down Expand Up @@ -101,3 +102,5 @@ int main()
## 参照
- [P0307R2 Making Optional Greater Equal Again](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0307r2.pdf)
- [LWG Issue 2934. `optional<const T>` doesn't compare with `T`](https://wg21.cmeerw.net/lwg/issue2934)
- [P1614R2 The Mothership has Landed](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1614r2.html)
- C++20での三方比較演算子の追加と、関連する演算子の自動導出
29 changes: 16 additions & 13 deletions reference/optional/optional/op_greater_equal.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,18 @@
```cpp
namespace std {
template <class T, class U>
constexpr bool operator>=(const optional<T>& x, const optional<U>& y); // (1)

template <class T>
constexpr bool operator>=(const optional<T>& x, nullopt_t) noexcept; // (2)
template <class T>
constexpr bool operator>=(nullopt_t, const optional<T>& y) noexcept; // (3)
constexpr bool operator>=(const optional<T>& x, const optional<U>& y); // (1) C++17

template <class T, class U>
constexpr bool operator>=(const optional<T>& x, const U& y); // (4)
constexpr bool operator>=(const optional<T>& x, const U& y); // (2) C++17
template <class T, class U>
constexpr bool operator>=(const U& x, const optional<T>& y); // (5)
constexpr bool operator>=(const U& x, const optional<T>& y); // (3) C++17

// operator<=>により、以下のオーバーロードが使用可能になる (C++20)
template <class T>
constexpr bool operator>=(const optional<T>& x, nullopt_t) noexcept; // (4) C++17
template <class T>
constexpr bool operator>=(nullopt_t, const optional<T>& y) noexcept; // (5) C++17
}
```
* nullopt_t[link /reference/optional/nullopt_t.md]
Expand All @@ -27,15 +28,15 @@ namespace std {
## 要件
- (1), (4), (5) : 型`T`と型`U`が`>=`演算子で比較可能であること
- (1), (2), (3) : 型`T`と型`U`が`>=`演算子で比較可能であること
## 戻り値
- (1) : `x`と`y`がどちらも有効値を持っていれば、有効値同士を`>=`演算子で比較した結果を返す。`y`が有効値を持っていなければ`true`を返す。`x`が有効値を持っていなければ`false`を返す
- (2) : `true`を返す
- (3) : `!x.`[`has_value()`](has_value.md)を返す
- (4) : `return x.`[`has_value()`](has_value.md) `? x.`[`value()`](value.md) `>= y : false;`
- (5) : `return y.`[`has_value()`](has_value.md) `? x >= y.`[`value()`](value.md) `: true;`
- (2) : `return x.`[`has_value()`](has_value.md) `? x.`[`value()`](value.md) `>= y : false;`
- (3) : `return y.`[`has_value()`](has_value.md) `? x >= y.`[`value()`](value.md) `: true;`
- (4) : `true`を返す
- (5) : `!x.`[`has_value()`](has_value.md)を返す
## 例
Expand Down Expand Up @@ -101,3 +102,5 @@ int main()
## 参照
- [P0307R2 Making Optional Greater Equal Again](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0307r2.pdf)
- [LWG Issue 2934. `optional<const T>` doesn't compare with `T`](https://wg21.cmeerw.net/lwg/issue2934)
- [P1614R2 The Mothership has Landed](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1614r2.html)
- C++20での三方比較演算子の追加と、関連する演算子の自動導出
29 changes: 16 additions & 13 deletions reference/optional/optional/op_less.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,18 @@
```cpp
namespace std {
template <class T, class U>
constexpr bool operator<(const optional<T>& x, const optional<U>& y); // (1)

template <class T>
constexpr bool operator<(const optional<T>& x, nullopt_t) noexcept; // (2)
template <class T>
constexpr bool operator<(nullopt_t, const optional<T>& y) noexcept; // (3)
constexpr bool operator<(const optional<T>& x, const optional<U>& y); // (1) C++17

template <class T, class U>
constexpr bool operator<(const optional<T>& x, const U& y); // (4)
constexpr bool operator<(const optional<T>& x, const U& y); // (2) C++17
template <class T, class U>
constexpr bool operator<(const U& x, const optional<T>& y); // (5)
constexpr bool operator<(const U& x, const optional<T>& y); // (3) C++17

// operator<=>により、以下のオーバーロードが使用可能になる (C++20)
template <class T>
constexpr bool operator<(const optional<T>& x, nullopt_t) noexcept; // (4) C++17
template <class T>
constexpr bool operator<(nullopt_t, const optional<T>& y) noexcept; // (5) C++17
}
```
* nullopt_t[link /reference/optional/nullopt_t.md]
Expand All @@ -27,15 +28,15 @@ namespace std {
## 要件
- (1), (4), (5) : 型`T`と型`U`が`<`演算子で比較可能であること
- (1), (2), (3) : 型`T`と型`U`が`<`演算子で比較可能であること
## 戻り値
- (1) : `x`と`y`がどちらも有効値を持っていれば、有効値同士を`<`演算子で比較した結果を返す。`y`が有効値を持っていなければ`false`を返す。`x`が有効値を持っていなければ`true`を返す
- (2) : `false`を返す
- (3) : `y`が有効値を持っていれば`true`、そうでなければ`false`を返す
- (4) : `return x.`[`has_value()`](has_value.md) `? x.`[`value()`](value.md) `< y : true;`
- (5) : `return y.`[`has_value()`](has_value.md) `? x < y.`[`value()`](value.md) `: false;`
- (2) : `return x.`[`has_value()`](has_value.md) `? x.`[`value()`](value.md) `< y : true;`
- (3) : `return y.`[`has_value()`](has_value.md) `? x < y.`[`value()`](value.md) `: false;`
- (4) : `false`を返す
- (5) : `y`が有効値を持っていれば`true`、そうでなければ`false`を返す
## 例
Expand Down Expand Up @@ -101,3 +102,5 @@ int main()
## 参照
- [P0307R2 Making Optional Greater Equal Again](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0307r2.pdf)
- [LWG Issue 2934. `optional<const T>` doesn't compare with `T`](https://wg21.cmeerw.net/lwg/issue2934)
- [P1614R2 The Mothership has Landed](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1614r2.html)
- C++20での三方比較演算子の追加と、関連する演算子の自動導出
Loading

0 comments on commit b4577ca

Please sign in to comment.