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