Skip to content

Commit

Permalink
expected: unexpected<E>(#1066)
Browse files Browse the repository at this point in the history
  • Loading branch information
yohhoy committed Feb 9, 2023
1 parent 31bdb1a commit a69e754
Show file tree
Hide file tree
Showing 21 changed files with 564 additions and 42 deletions.
3 changes: 3 additions & 0 deletions reference/exception/unexpected.md
Expand Up @@ -13,6 +13,9 @@ namespace std {
この関数はC++11から非推奨となり、C++17で削除された。`throw`キーワードの代わりに使用する[`noexcept`キーワード](/lang/cpp11/noexcept.md)では、指定外の例外が発生することによるエラーは起こらない。
C++23から、同名の[`std::unexpected<E>`クラステンプレート](/reference/expected/unexpected.md)が追加される。C++17で削除された名前の再利用となっているが、この関数と同クラステンプレートの間に機能的な関係は一切ない。
## 概要
例外指定のある関数内で、指定外の例外が発生した時に呼び出される例外ハンドラを直接呼び出す。
Expand Down
8 changes: 4 additions & 4 deletions reference/expected/expected.void/op_assign.md
Expand Up @@ -54,13 +54,13 @@ constexpr expected& operator=(unexpected<G>&& e); // (4)
- `this`がエラーを保持し、`rhs`が正常値を保持していたら、`unex`を破棄し`has_value = true;`
- `this``rhs`が共にエラー値を保持していたら、`unex =` [`std::move`](/reference/utility/move.md)`(rhs.`[`error()`](error.md)`)`
- (3) : 次の処理と等価
- `this`が正常値を保持していたら、[`construct_at`](/reference/memory/construct_at.md)`(`[`addressof`](/reference/memory/addressof.md)`(unex), val,` [`std::forward`](/reference/utility/forward.md)`<const G&>(e.`[`error()`](../unexpected/error.md.nolink)`));
- `this`が正常値を保持していたら、[`construct_at`](/reference/memory/construct_at.md)`(`[`addressof`](/reference/memory/addressof.md)`(unex), val,` [`std::forward`](/reference/utility/forward.md)`<const G&>(e.`[`error()`](../unexpected/error.md)`));
has_val = false;`
- `this`がエラー値を保持していたら、`unex =` [`std::forward`](/reference/utility/forward.md)`<const G&>(e.`[`error()`](../unexpected/error.md.nolink)`);`
- `this`がエラー値を保持していたら、`unex =` [`std::forward`](/reference/utility/forward.md)`<const G&>(e.`[`error()`](../unexpected/error.md)`);`
- (4) : 次の処理と等価
- `this`が正常値を保持していたら、[`construct_at`](/reference/memory/construct_at.md)`(`[`addressof`](/reference/memory/addressof.md)`(unex), val,` [`std::forward`](/reference/utility/forward.md)`<G>(e.`[`error()`](../unexpected/error.md.nolink)`));
- `this`が正常値を保持していたら、[`construct_at`](/reference/memory/construct_at.md)`(`[`addressof`](/reference/memory/addressof.md)`(unex), val,` [`std::forward`](/reference/utility/forward.md)`<G>(e.`[`error()`](../unexpected/error.md)`));
has_val = false;`
- `this`がエラー値を保持していたら、`unex =` [`std::forward`](/reference/utility/forward.md)`<G>(e.`[`error()`](../unexpected/error.md.nolink)`);`
- `this`がエラー値を保持していたら、`unex =` [`std::forward`](/reference/utility/forward.md)`<G>(e.`[`error()`](../unexpected/error.md)`);`


## 戻り値
Expand Down
4 changes: 2 additions & 2 deletions reference/expected/expected.void/op_constructor.md
Expand Up @@ -75,8 +75,8 @@ constexpr explicit expected(unexpect_t, initializer_list<U> il, Args&&... args);
- (3) : `rhs`がエラー値を保持していれば、[`std::move`](/reference/utility/move.md)`(rhs.`[`error()`](error.md)`)`でエラー値を直接非リスト初期化する。
- (4) : `rhs`がエラー値を保持していれば、[`std::forward`](/reference/utility/forward.md)`<const G&>(rhs.`[`error()`](error.md)`)`でエラー値を直接非リスト初期化する。
- (5) : `rhs`がエラー値を保持していれば、[`std::forward`](/reference/utility/forward.md)`<G>(rhs.`[`error()`](error.md)`)`でエラー値を直接非リスト初期化する。
- (6) : [`std::forward`](/reference/utility/forward.md)`<const G&>(e.`[`error()`](../unexpected/error.md.nolink)`)`でエラー値を直接非リスト初期化する。
- (7) : [`std::forward`](/reference/utility/forward.md)`<G>(e.`[`error()`](../unexpected/error.md.nolink)`)`でエラー値を直接非リスト初期化する。
- (6) : [`std::forward`](/reference/utility/forward.md)`<const G&>(e.`[`error()`](../unexpected/error.md)`)`でエラー値を直接非リスト初期化する。
- (7) : [`std::forward`](/reference/utility/forward.md)`<G>(e.`[`error()`](../unexpected/error.md)`)`でエラー値を直接非リスト初期化する。
- (9) : [`std::forward`](/reference/utility/forward.md)`<Args>(args)...`でエラー値を直接非リスト初期化する。
- (10) : `il,` [`std::forward`](/reference/utility/forward.md)`<Args>(args)...`でエラー値を直接非リスト初期化する。
Expand Down
8 changes: 4 additions & 4 deletions reference/expected/expected.void/op_equal.md
Expand Up @@ -20,20 +20,20 @@ friend constexpr bool operator==(const unexpected<E2>& e, const expected& x);
* unexpected[link ../unexpected.md]
## 概要
- (1) : `unexpected`オブジェクト同士の等値比較を行う。
- (2), (3) : `unexpected`オブジェクトとエラー値の等値比較を行う。
- (1) : `expected`オブジェクト同士の等値比較を行う。
- (2), (3) : `expected`オブジェクトとエラー値の等値比較を行う。
## 適格要件
- (1) : 式`x.`[`error()`](error.md) `== y.`[`error()`](error.md)が適格であり、その結果を`bool`へ変換可能であること。
- (2), (3) : 式`x.`[`error()`](error.md) `== e.`[`error()`](../unexpected/error.md.nolink)が適格であり、その結果を`bool`へ変換可能であること。
- (2), (3) : 式`x.`[`error()`](error.md) `== e.`[`error()`](../unexpected/error.md)が適格であり、その結果を`bool`へ変換可能であること。
## 戻り値
- (1) : 次の値を返す
- `x.`[`has_value()`](has_value.md)と`y.`[`has_value()`](has_value.md)が異なるとき、`false`
- そうでなければ、`x.`[`has_value()`](has_value.md) `|| static_cast<bool>(x.`[`error()`](error.md) `== y.`[`error()`](error.md)`)`
- (2), (3) : `!x.`[`has_value()`](has_value.md) `&& static_cast<bool>(x.`[`error()`](error.md) `== e.`[`error()`](../unexpected/error.md.nolink)`)`
- (2), (3) : `!x.`[`has_value()`](has_value.md) `&& static_cast<bool>(x.`[`error()`](error.md) `== e.`[`error()`](../unexpected/error.md)`)`
## 例
Expand Down
6 changes: 3 additions & 3 deletions reference/expected/expected.void/op_not_equal.md
Expand Up @@ -21,13 +21,13 @@ friend constexpr bool operator!=(const unexpected<E2>& e, const expected& x);
* unexpected[link ../unexpected.md]
## 概要
- (1) : `unexpected`オブジェクト同士の非等値比較を行う。
- (2), (3) : `unexpected`オブジェクトとエラー値の非等値比較を行う。
- (1) : `expected`オブジェクト同士の非等値比較を行う。
- (2), (3) : `expected`オブジェクトとエラー値の非等値比較を行う。
## 適格要件
- (1) : 式`x.`[`error()`](error.md) `== y.`[`error()`](error.md)が適格であり、その結果を`bool`へ変換可能であること。
- (2), (3) : 式`x.`[`error()`](error.md) `== e.`[`error()`](../unexpected/error.md.nolink)が適格であり、その結果を`bool`へ変換可能であること。
- (2), (3) : 式`x.`[`error()`](error.md) `== e.`[`error()`](../unexpected/error.md)が適格であり、その結果を`bool`へ変換可能であること。
## 戻り値
Expand Down
2 changes: 1 addition & 1 deletion reference/expected/expected.void/swap_free.md
Expand Up @@ -10,7 +10,7 @@
friend constexpr void swap(expected& x, expected& y)
noexcept(noexcept(x.swap(y)));
```
* swap[link swap.md]
* x.swap(y)[link swap.md]
## 概要
2つの`expected`オブジェクトを入れ替える。
Expand Down
2 changes: 1 addition & 1 deletion reference/expected/expected.void/value.md
Expand Up @@ -43,7 +43,7 @@ int main()
}
```
* value()[color ff0000]
* error()[link ../unexpected/error.md.nolink]
* error()[link ../bad_expected_access/error.md.nolink]
* std::unexpected[link ../unexpected.md]
* std::bad_expected_access[link ../bad_expected_access.md]

Expand Down
8 changes: 4 additions & 4 deletions reference/expected/expected/op_assign.md
Expand Up @@ -107,13 +107,13 @@ constexpr void reinit-expected(T& newval, U& oldval, Args&&... args) {
- `this`が正常値を保持していたら、`val =` [`std::forward`](/reference/utility/forward.md)`<U>(v)`
- `this`がエラー値を保持していたら、`reinit-expected(val, unex,` [`std::forward`](/reference/utility/forward.md)`<U>(v)); has_val = true;`
- (4) : 次の処理と等価
- `this`が正常値を保持していたら、`reinit-expected(unex, val,` [`std::forward`](/reference/utility/forward.md)`<const G&>(e.`[`error()`](../unexpected/error.md.nolink)`));
- `this`が正常値を保持していたら、`reinit-expected(unex, val,` [`std::forward`](/reference/utility/forward.md)`<const G&>(e.`[`error()`](../unexpected/error.md)`));
has_val = false;`
- `this`がエラー値を保持していたら、`unex =` [`std::forward`](/reference/utility/forward.md)`<const G&>(e.`[`error()`](../unexpected/error.md.nolink)`);`
- `this`がエラー値を保持していたら、`unex =` [`std::forward`](/reference/utility/forward.md)`<const G&>(e.`[`error()`](../unexpected/error.md)`);`
- (5) : 次の処理と等価
- `this`が正常値を保持していたら、`reinit-expected(unex, val,` [`std::forward`](/reference/utility/forward.md)`<G>(e.`[`error()`](../unexpected/error.md.nolink)`));
- `this`が正常値を保持していたら、`reinit-expected(unex, val,` [`std::forward`](/reference/utility/forward.md)`<G>(e.`[`error()`](../unexpected/error.md)`));
has_val = false;`
- `this`がエラー値を保持していたら、`unex =` [`std::forward`](/reference/utility/forward.md)`<G>(e.`[`error()`](../unexpected/error.md.nolink)`);`
- `this`がエラー値を保持していたら、`unex =` [`std::forward`](/reference/utility/forward.md)`<G>(e.`[`error()`](../unexpected/error.md)`);`


## 戻り値
Expand Down
4 changes: 2 additions & 2 deletions reference/expected/expected/op_constructor.md
Expand Up @@ -108,8 +108,8 @@ constexpr bool converts-from-any-cvref =
- (4) : `rhs`が正常値を保持していれば、[`std::forward`](/reference/utility/forward.md)`<const U&>(`[`*rhs`](op_deref.md)`)`で正常値を直接非リスト初期化する。そうでなければ、[`std::forward`](/reference/utility/forward.md)`<const G&>(rhs.`[`error()`](error.md)`)`でエラー値を直接非リスト初期化する。
- (5) : `rhs`が正常値を保持していれば、[`std::forward`](/reference/utility/forward.md)`<U>(`[`*rhs`](op_deref.md)`)`で正常値を直接非リスト初期化する。そうでなければ、[`std::forward`](/reference/utility/forward.md)`<G>(rhs.`[`error()`](error.md)`)`でエラー値を直接非リスト初期化する。
- (6) : [`std::forward`](/reference/utility/forward.md)`<U>(v)`で正常値を直接非リスト初期化する。
- (7) : [`std::forward`](/reference/utility/forward.md)`<const G&>(e.`[`error()`](../unexpected/error.md.nolink)`)`でエラー値を直接非リスト初期化する。
- (8) : [`std::forward`](/reference/utility/forward.md)`<G>(e.`[`error()`](../unexpected/error.md.nolink)`)`でエラー値を直接非リスト初期化する。
- (7) : [`std::forward`](/reference/utility/forward.md)`<const G&>(e.`[`error()`](../unexpected/error.md)`)`でエラー値を直接非リスト初期化する。
- (8) : [`std::forward`](/reference/utility/forward.md)`<G>(e.`[`error()`](../unexpected/error.md)`)`でエラー値を直接非リスト初期化する。
- (9) : [`std::forward`](/reference/utility/forward.md)`<Args>(args)...`で正常値を直接非リスト初期化する。
- (10) : `il,` [`std::forward`](/reference/utility/forward.md)`<Args>(args)...`で正常値を直接非リスト初期化する。
- (11) : [`std::forward`](/reference/utility/forward.md)`<Args>(args)...`でエラー値を直接非リスト初期化する。
Expand Down
10 changes: 5 additions & 5 deletions reference/expected/expected/op_equal.md
Expand Up @@ -25,15 +25,15 @@ friend constexpr bool operator==(const unexpected<E2>& e, const expected& x); //
* unexpected[link ../unexpected.md]
## 概要
- (1) : `unexpected`オブジェクト同士の等値比較を行う。
- (2), (3) : `unexpected`オブジェクトと正常値の等値比較を行う。
- (4), (5) : `unexpected`オブジェクトとエラー値の等値比較を行う。
- (1) : `expected`オブジェクト同士の等値比較を行う。
- (2), (3) : `expected`オブジェクトと正常値の等値比較を行う。
- (4), (5) : `expected`オブジェクトとエラー値の等値比較を行う。
## 適格要件
- (1) : 式[`*x`](op_deref.md) `==` [`*y`](op_deref.md)および式`x.`[`error()`](error.md) `== y.`[`error()`](error.md)が適格であり、各式の結果を`bool`へ変換可能であること。
- (2), (3) : 式[`*x`](op_deref.md) `== v`が適格であり、その結果を`bool`へ変換可能であること。
- (4), (5) : 式`x.`[`error()`](error.md) `== e.`[`error()`](../unexpected/error.md.nolink)が適格であり、その結果を`bool`へ変換可能であること。
- (4), (5) : 式`x.`[`error()`](error.md) `== e.`[`error()`](../unexpected/error.md)が適格であり、その結果を`bool`へ変換可能であること。
## 戻り値
Expand All @@ -42,7 +42,7 @@ friend constexpr bool operator==(const unexpected<E2>& e, const expected& x); //
- `x.`[`has_value()`](has_value.md) `== true`のとき、[`*x`](op_deref.md) `==` [`*y`](op_deref.md)
- `x.`[`error()`](error.md) `== y.`[`error()`](error.md)
- (2), (3) : `x.`[`has_value()`](has_value.md) `&& static_cast<bool>(`[`*x`](op_deref.md) `== v)`
- (4), (5) : `!x.`[`has_value()`](has_value.md) `&& static_cast<bool>(x.`[`error()`](error.md) `== e.`[`error()`](../unexpected/error.md.nolink)`)`
- (4), (5) : `!x.`[`has_value()`](has_value.md) `&& static_cast<bool>(x.`[`error()`](error.md) `== e.`[`error()`](../unexpected/error.md)`)`
## 例
Expand Down
8 changes: 4 additions & 4 deletions reference/expected/expected/op_not_equal.md
Expand Up @@ -25,15 +25,15 @@ friend constexpr bool operator!=(const unexpected<E2>& e, const expected& x); //
* unexpected[link ../unexpected.md]
## 概要
- (1) : `unexpected`オブジェクト同士の非等値比較を行う。
- (2), (3) : `unexpected`オブジェクトと正常値の非等値比較を行う。
- (4), (5) : `unexpected`オブジェクトとエラー値の非等値比較を行う。
- (1) : `expected`オブジェクト同士の非等値比較を行う。
- (2), (3) : `expected`オブジェクトと正常値の非等値比較を行う。
- (4), (5) : `expected`オブジェクトとエラー値の非等値比較を行う。
## 適格要件
- (1) : 式[`*x`](op_deref.md) `==` [`*y`](op_deref.md)および式`x.`[`error()`](error.md) `== y.`[`error()`](error.md)が適格であり、各式の結果を`bool`へ変換可能であること。
- (2), (3) : 式[`*x`](op_deref.md) `== v`が適格であり、その結果を`bool`へ変換可能であること。
- (4), (5) : 式`x.`[`error()`](error.md) `== e.`[`error()`](../unexpected/error.md.nolink)が適格であり、その結果を`bool`へ変換可能であること。
- (4), (5) : 式`x.`[`error()`](error.md) `== e.`[`error()`](../unexpected/error.md)が適格であり、その結果を`bool`へ変換可能であること。
## 戻り値
Expand Down
2 changes: 1 addition & 1 deletion reference/expected/expected/swap_free.md
Expand Up @@ -9,7 +9,7 @@
friend constexpr void swap(expected& x, expected& y)
noexcept(noexcept(x.swap(y)));
```
* swap[link swap.md]
* x.swap(y)[link swap.md]
## 概要
2つの`expected`オブジェクトを入れ替える。
Expand Down
2 changes: 1 addition & 1 deletion reference/expected/expected/value.md
Expand Up @@ -48,7 +48,7 @@ int main()
}
```
* value()[color ff0000]
* error()[link ../unexpected/error.md.nolink]
* error()[link ../bad_expected_access/error.md.nolink]
* std::unexpected[link ../unexpected.md]
* std::bad_expected_access[link ../bad_expected_access.md]

Expand Down
21 changes: 11 additions & 10 deletions reference/expected/unexpected.md
Expand Up @@ -12,7 +12,7 @@ namespace std {
```
## 概要
`unexpected`クラスは、任意の型`E`の値をエラー値として表現する。
`unexpected`クラスは、[`std::expected<T, E>`](expected.md)に格納される任意の型`E`の値をエラー値として表現する。
## 適格要件
Expand All @@ -24,41 +24,42 @@ namespace std {
| 名前 | 説明 | 対応バージョン |
|-----------------|----------------|-------|
| [`(constructor)`](unexpected/op_constructor.md.nolink) | コンストラクタ | C++23 |
| [`(destructor)`](unexpected/op_destructor.md.nolink) | デストラクタ | C++23 |
| [`(constructor)`](unexpected/op_constructor.md) | コンストラクタ | C++23 |
| `(destructor)` | デストラクタ | C++23 |
### 代入
| 名前 | 説明 | 対応バージョン |
|-----------------|----------------|-------|
| [`operator=`](unexpected/op_assign.md.nolink) | 代入演算子 | C++23 |
| [`swap`](unexpected/swap.md.nolink) | 他の`unexpected`オブジェクトとデータを入れ替える | C++23 |
| `constexpr unexpected& operator=(const unexpected&) = default;` | コピー代入演算子 | C++23 |
| `constexpr unexpected& operator=(unexpected&&) = default;` | ムーブ代入演算子 | C++23 |
| [`swap`](unexpected/swap.md) | 他の`unexpected`オブジェクトとデータを入れ替える | C++23 |
### 値の観測
| 名前 | 説明 | 対応バージョン |
|-----------------|----------------|-------|
| [`error`](unexpected/error.md.nolink) | エラー値を取得する | C++23 |
| [`error`](unexpected/error.md) | 値を取得する | C++23 |
### 比較
| 名前 | 説明 | 対応バージョン |
|--------------|------------|-------|
| [`operator==`](unexpected/op_equal.md.nolink) | 等値比較 | C++23 |
| [`operator!=`](unexpected/op_not_equal.md.nolink) | 非等値比較 | C++23 |
| [`operator==`](unexpected/op_equal.md) | 等値比較 | C++23 |
| [`operator!=`](unexpected/op_not_equal.md) | 非等値比較 | C++23 |
## 非メンバ関数
| 名前 | 説明 | 対応バージョン |
|------|------|-------|
| [`swap`](unexpected/swap_free.md.nolink) | 他の`unexpected`オブジェクトとデータを入れ替える | C++23 |
| [`swap`](unexpected/swap_free.md) | 2つの`unexpected`オブジェクトを入れ替える | C++23 |
## 推論補助
| 名前 | 説明 | 対応バージョン |
|------|------|-------|
| [`(deduction_guide)`](unexpected/op_deduction_guide.md.nolink) | クラステンプレートの推論補助 | C++23 |
| [`(deduction_guide)`](unexpected/op_deduction_guide.md) | クラステンプレートの推論補助 | C++23 |
## 例
Expand Down
65 changes: 65 additions & 0 deletions reference/expected/unexpected/error.md
@@ -0,0 +1,65 @@
# error
* expected[meta header]
* function[meta id-type]
* std[meta namespace]
* unexpected[meta class]
* cpp23[meta cpp]

```cpp
constexpr const E& error() const & noexcept; // (1)
constexpr E& error() & noexcept; // (2)
constexpr const E&& error() const && noexcept; // (3)
constexpr E&& error() && noexcept; // (4)
```

## 概要
値を取得する。


## 戻り値
動作説明用のメンバ変数として、値を保持する`unex`を導入する。

- (1), (2) : `unex`
- (3), (4) : [`std::move`](/reference/utility/move.md)`(unex)`


## 例外
投げない


##
```cpp example
#include <cassert>
#include <expected>
#include <iostream>
#include <string>

int main()
{
std::unexpected<std::string> x{"ERR"};
std::cout << x.error() << std::endl;
}
```
* error()[color ff0000]
* std::unexpected[link ../unexpected.md]

### 出力
```
ERR
```


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

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


## 参照
- [P0323R12 std::expected](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p0323r12.html)
- [P2549R1 `std::unexpected<E>` should have `error()` as member accessor](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2549r1.html)

0 comments on commit a69e754

Please sign in to comment.