template<class F> constexpr auto transform(F&& f) &; // (1)
template<class F> constexpr auto transform(F&& f) const &; // (2)
template<class F> constexpr auto transform(F&& f) &&; // (3)
template<class F> constexpr auto transform(F&& f) const &&; // (4)
概要
正常値を保持していれば、正常値に対してf
を適用した結果をexpected
の正常値として格納して返す。
エラー値を保持していれば、そのまま返す。
実際には複数オーバーロードが提供されるが、大まかには下記シグニチャのようにみなせる。
transform
へは、引数リストに1個のT
型をとりReturn
型を返す関数や関数オブジェクトを与える。
template <class T, class E>
class expected {
template <class Return>
std::expected<Return, E> transform(function<Return(T)> func);
};
テンプレートパラメータ制約
- (1), (2) :
is_copy_constructible_v<E> == true
- (3), (4) :
is_move_constructible_v<E> == true
適格要件
- (1), (2) : 型
U
をremove_cvref_t<invoke_result_t<F, decltype(value())>>
としたとき、次を全て満たすことU
がexpected
の有効な正常値型であるU
が(CV修飾された)void
ではないとき、宣言U u(invoke(std::forward<F>(f), value()));
が妥当である
- (3), (4) : 型
U
をremove_cvref_t<invoke_result_t<F, decltype(std::move(value()))>>
としたとき、次を全て満たすことU
がexpected
の有効な正常値型であるU
が(CV修飾された)void
ではないとき、宣言U u(invoke(std::forward<F>(f), std::move(value())));
が妥当である
効果
- (1), (2) : 次の効果をもつ
- エラー値を保持していたら、
expected<U, E>(unexpect, error())
を返す。 - 型
U
が(CV修飾された)void
でなければ、正常値をinvoke(std::forward<F>(f), value())
で直接非リスト初期化したexpected<U, E>
オブジェクトを返す。 - そうでなければ、
invoke(std::forward<F>(f), value())
を評価し、expected<U, E>()
を返す。
- エラー値を保持していたら、
- (3), (4) : 次の効果をもつ
備考
transform
は、メソッドチェーンをサポートするモナド風(monadic)操作として導入された。
例
#include <cassert>
#include <expected>
#include <numeric>
#include <string>
#include <vector>
// 1..N数列を生成する関数
std::vector<int> make_seq(int n)
{
std::vector<int> seq(n, 0);
std::iota(seq.begin(), seq.end(), 1);
return seq;
}
int main()
{
std::expected<int, std::string> v1 = 3;
assert((v1.transform(make_seq).value() == std::vector<int>{1,2,3}));
std::expected<int, std::string> e1 = std::unexpected{"NaN"};
assert(e1.transform(make_seq).error() == "NaN");
}
出力
バージョン
言語
- C++23
処理系
- Clang: ??
- GCC: 13.0 ✅
- ICC: ??
- Visual C++: ??