Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
optional: P0798R8 and_then/transform/or_else追加(#1057)
- Loading branch information
Showing
5 changed files
with
350 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
# and_then | ||
* optional[meta header] | ||
* function template[meta id-type] | ||
* std[meta namespace] | ||
* optional[meta class] | ||
* cpp23[meta cpp] | ||
|
||
```cpp | ||
template <class F> constexpr auto and_then(F&& f) &; // (1) | ||
template <class F> constexpr auto and_then(F&& f) &&; // (2) | ||
template <class F> constexpr auto and_then(F&& f) const&; // (3) | ||
template <class F> constexpr auto and_then(F&& f) const&&; // (4) | ||
``` | ||
## 概要 | ||
有効値を保持していれば、値に対して`f`を適用した結果を`optional`として返す。 | ||
有効値を保持していなければ、[`std::nullopt`](../nullopt_t.md)を返す。 | ||
実際には複数オーバーロードが提供されるが、大まかには下記シグニチャのようにみなせる。 | ||
`and_then`へは、引数リストに1個の`T`型をとり`std::optional<Return>`型を返す関数や関数オブジェクトを与える。 | ||
```cpp | ||
template <class T> | ||
class optional { | ||
template <class Return> | ||
std::optional<Return> and_then(function<std::optional<Return>(T)> func); | ||
}; | ||
``` | ||
* function[link /reference/functional/function.md] | ||
|
||
|
||
## 適格要件 | ||
説明用の`U`型を次の通りとする: | ||
|
||
- (1), (3) : [`invoke_result_t`](/reference/type_traits/invoke_result.md)`<F, decltype(`[`value()`](value.md)`)>` | ||
- (2), (4) : [`invoke_result_t`](/reference/type_traits/invoke_result.md)`<F, decltype(`[`std::move`](/reference/utility/move.md)`(`[`value()`](value.md)`))>` | ||
|
||
[`remove_cvref_t`](/reference/type_traits/remove_cvref.md)`<U>`は`optional`の特殊化であること | ||
|
||
|
||
## 効果 | ||
- (1), (3) : 次と等価 | ||
|
||
```cpp | ||
if (*this) { | ||
return invoke(std::forward<F>(f), value()); | ||
} else { | ||
return remove_cvref_t<U>(); | ||
} | ||
``` | ||
|
||
- (2), (4) : 次と等価 | ||
|
||
```cpp | ||
if (*this) { | ||
return invoke(std::forward<F>(f), std::move(value())); | ||
} else { | ||
return remove_cvref_t<U>(); | ||
} | ||
``` | ||
|
||
|
||
## 備考 | ||
`and_then`は、メソッドチェーンをサポートするモナド風(monadic)操作として導入された。 | ||
関数型プログラミングの文脈における Monadic Bind 操作に対応する。 | ||
|
||
|
||
## 例 | ||
```cpp example | ||
#include <cassert> | ||
#include <optional> | ||
|
||
// 正数なら2倍/それ以外は無効値を返す関数 | ||
std::optional<int> twice(int n) | ||
{ | ||
if (0 < n) { | ||
return n * 2; | ||
} else { | ||
return std::nullopt; | ||
} | ||
} | ||
|
||
int main() | ||
{ | ||
std::optional<int> o1 = 2; | ||
assert(o1.and_then(twice).value() == 4); | ||
|
||
std::optional<int> o2 = -1; | ||
assert(not o2.and_then(twice).has_value()); | ||
|
||
std::optional<int> o3 = std::nullopt; | ||
assert(not o3.and_then(twice).has_value()); | ||
} | ||
``` | ||
* and_then[color ff0000] | ||
* std::nullopt[link ../nullopt_t.md] | ||
* value()[link value.md] | ||
* has_value()[link has_value.md] | ||
### 出力 | ||
``` | ||
``` | ||
## バージョン | ||
### 言語 | ||
- C++23 | ||
### 処理系 | ||
- [Clang](/implementation.md#clang): ?? | ||
- [GCC](/implementation.md#gcc): ?? | ||
- [ICC](/implementation.md#icc): ?? | ||
- [Visual C++](/implementation.md#visual_cpp): ?? | ||
## 関連項目 | ||
- [`transform`](transform.md) | ||
- [`or_else`](or_else.md) | ||
## 参照 | ||
- [P0798R8 Monadic operations for std::optional](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0798r8.html) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
# or_else | ||
* optional[meta header] | ||
* function template[meta id-type] | ||
* std[meta namespace] | ||
* optional[meta class] | ||
* cpp23[meta cpp] | ||
|
||
```cpp | ||
template<class F> constexpr optional or_else(F&& f) const &; // (1) | ||
template<class F> constexpr optional or_else(F&& f) &&; // (2) | ||
``` | ||
## 概要 | ||
有効値を保持していれば、なにもしない。 | ||
有効値を保持していなければ、`f()`の呼び出し結果を`optional`として返す。 | ||
実際には複数オーバーロードが提供されるが、大まかには下記シグニチャのようにみなせる。 | ||
`or_else`へは、空の引数リストをとり`std::optional<T>`へ変換可能な`Return`型を返す関数や関数オブジェクトを与える。 | ||
```cpp | ||
template <class T> | ||
class optional { | ||
template <class Return> | ||
std::optional<T> or_else(function<Return()> func); | ||
}; | ||
``` | ||
* function[link /reference/functional/function.md] | ||
|
||
|
||
## テンプレートパラメータ制約 | ||
- (1) : `F`は[`invocable<>`](/reference/concepts/invocable.md)のモデル、かつ`T`は[`copy_constructible`](/reference/concepts/copy_constructible.md)のモデルであること | ||
- (2) : `F`は[`invocable<>`](/reference/concepts/invocable.md)のモデル、かつ`T`は[`move_constructible`](/reference/concepts/move_constructible.md)のモデルであること | ||
|
||
|
||
## 適格要件 | ||
[`is_same_v`](/reference/type_traits/is_same.md)`<`[`remove_cvref_t`](/reference/type_traits/remove_cvref.md)`<`[`invoke_result_t`](/reference/type_traits/invoke_result.md)`<F>>, optional>`が`true`であること | ||
|
||
|
||
## 効果 | ||
- (1) : 次と等価 | ||
|
||
```cpp | ||
if (*this) { | ||
return *this; | ||
} else { | ||
return std::forward<F>(f)(); | ||
} | ||
``` | ||
|
||
- (2) : 次と等価 | ||
|
||
```cpp | ||
if (*this) { | ||
return std::move(*this); | ||
} else { | ||
return std::forward<F>(f)(); | ||
} | ||
``` | ||
|
||
|
||
## 備考 | ||
`or_else`は、メソッドチェーンをサポートするモナド風(monadic)操作として導入された。 | ||
|
||
|
||
## 例 | ||
```cpp example | ||
#include <cassert> | ||
#include <optional> | ||
|
||
std::optional<int> defvalue() | ||
{ | ||
return 42; | ||
} | ||
|
||
int main() | ||
{ | ||
std::optional<int> o1 = 1; | ||
assert(o1.or_else(defvalue).value() == 1); | ||
|
||
std::optional<int> o2 = std::nullopt; | ||
assert(o2.or_else(defvalue).value() == 42); | ||
} | ||
``` | ||
* or_else[color ff0000] | ||
* std::nullopt[link ../nullopt_t.md] | ||
* value()[link value.md] | ||
|
||
|
||
### 出力 | ||
``` | ||
``` | ||
|
||
|
||
## バージョン | ||
### 言語 | ||
- C++23 | ||
|
||
### 処理系 | ||
- [Clang](/implementation.md#clang): ?? | ||
- [GCC](/implementation.md#gcc): ?? | ||
- [ICC](/implementation.md#icc): ?? | ||
- [Visual C++](/implementation.md#visual_cpp): ?? | ||
|
||
|
||
## 関連項目 | ||
- [`and_then`](and_then.md) | ||
- [`transform`](transform.md) | ||
- [`value_or`](value_or.md) | ||
|
||
|
||
## 参照 | ||
- [P0798R8 Monadic operations for std::optional](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0798r8.html) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
# transform | ||
* optional[meta header] | ||
* function template[meta id-type] | ||
* std[meta namespace] | ||
* optional[meta class] | ||
* cpp23[meta cpp] | ||
|
||
```cpp | ||
template <class F> constexpr auto transform(F&& f) &; // (1) | ||
template <class F> constexpr auto transform(F&& f) &&; // (2) | ||
template <class F> constexpr auto transform(F&& f) const&; // (3) | ||
template <class F> constexpr auto transform(F&& f) const&&; // (4) | ||
``` | ||
## 概要 | ||
有効値を保持していれば、値に対して`f`を適用した結果を`optional`に格納して返す。 | ||
有効値を保持していなければ、[`std::nullopt`](../nullopt_t.md)を返す。 | ||
実際には複数オーバーロードが提供されるが、大まかには下記シグニチャのようにみなせる。 | ||
`transform`へは、引数リストに1個の`T`型をとり`Return`型を返す関数や関数オブジェクトを与える。 | ||
```cpp | ||
template <class T> | ||
class optional { | ||
template <class Return> | ||
std::optional<Return> transform(function<Return(T)> func); | ||
}; | ||
``` | ||
* function[link /reference/functional/function.md] | ||
|
||
|
||
説明用の`U`型を次の通りとする: | ||
|
||
- (1), (3) : [`invoke_result_t`](/reference/type_traits/invoke_result.md)`<F, decltype(`[`value()`](value.md)`)>` | ||
- (2), (4) : [`invoke_result_t`](/reference/type_traits/invoke_result.md)`<F, decltype(`[`std::move`](/reference/utility/move.md)`(`[`value()`](value.md)`))>` | ||
|
||
|
||
## 適格要件 | ||
- (1), (3) : | ||
- `U`型は[`in_place_t`](/reference/utility/in_place_t.md), [`nullopt_t`](nullopt_t.md)いずれでもなく、非配列オブジェクト型であること。 | ||
- ある変数`u`の宣言 `U u(`[`invoke`](/reference/functional/invoke.md)`(`[`std::forward`](/reference/utility/forward.md)`<F>(f),` [`value()`](value.md)`));` が妥当であること。 | ||
- (2), (4) : | ||
- `U`型は[`in_place_t`](/reference/utility/in_place_t.md), [`nullopt_t`](nullopt_t.md)いずれでもなく、非配列オブジェクト型であること。 | ||
- ある変数`u`の宣言 `U u(`[`invoke`](/reference/functional/invoke.md)`(`[`std::forward`](/reference/utility/forward.md)`<F>(f),` [`std::move`](/reference/utility/move.md)`(`[`value()`](value.md)`)));` が妥当であること。 | ||
|
||
|
||
## 効果 | ||
- (1), (3) : `*this`が有効値を保持するときは、[`invoke`](/reference/functional/invoke.md)`(`[`std::forward`](/reference/utility/forward.md)`<F>(f),` [`value()`](value.md)`)`で非リスト初期化した`optional<U>`オブジェクトを返す。有効値を保持しないときは、`optional<U>()`を返す。 | ||
- (2), (4) : `*this`が有効値を保持するときは、[`invoke`](/reference/functional/invoke.md)`(`[`std::forward`](/reference/utility/forward.md)`<F>(f),` [`std::move`](/reference/utility/move.md)`(`[`value()`](value.md)`))`で非リスト初期化した`optional<U>`オブジェクトを返す。有効値を保持しないときは、`optional<U>()`を返す。 | ||
|
||
|
||
## 備考 | ||
`transform`は、メソッドチェーンをサポートするモナド風(monadic)操作として導入された。 | ||
関数型プログラミングの文脈における Functor Map 操作に対応する。 | ||
|
||
|
||
## 例 | ||
```cpp example | ||
#include <cassert> | ||
#include <optional> | ||
|
||
int twice(int n) | ||
{ | ||
return n * 2; | ||
} | ||
|
||
int main() | ||
{ | ||
std::optional<int> o1 = 2; | ||
assert(o1.transform(twice).value() == 4); | ||
|
||
std::optional<int> o2 = std::nullopt; | ||
assert(not o2.transform(twice).has_value()); | ||
} | ||
``` | ||
* transform[color ff0000] | ||
* std::nullopt[link ../nullopt_t.md] | ||
* value()[link value.md] | ||
* has_value()[link has_value.md] | ||
### 出力 | ||
``` | ||
``` | ||
## バージョン | ||
### 言語 | ||
- C++23 | ||
### 処理系 | ||
- [Clang](/implementation.md#clang): ?? | ||
- [GCC](/implementation.md#gcc): ?? | ||
- [ICC](/implementation.md#icc): ?? | ||
- [Visual C++](/implementation.md#visual_cpp): ?? | ||
## 関連項目 | ||
- [`and_then`](and_then.md) | ||
- [`or_else`](or_else.md) | ||
## 参照 | ||
- [P0798R8 Monadic operations for std::optional](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0798r8.html) |