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
型を返す関数や関数オブジェクトを与える。
template <class T>
class optional {
template <class Return>
std::optional<T> or_else(function<Return()> func);
};
テンプレートパラメータ制約
- (1) :
F
はinvocable<>
のモデル、かつT
はcopy_constructible
のモデルであること - (2) :
F
はinvocable<>
のモデル、かつT
はmove_constructible
のモデルであること
適格要件
is_same_v<remove_cvref_t<invoke_result_t<F>>, optional>
がtrue
であること
効果
-
(1) : 次と等価
if (*this) { return *this; } else { return std::forward<F>(f)(); }
-
(2) : 次と等価
if (*this) { return std::move(*this); } else { return std::forward<F>(f)(); }
備考
or_else
は、メソッドチェーンをサポートするモナド風(monadic)操作として導入された。
例
基本的な使い方
#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);
}
出力
メソッドチェインとしての使い方
#include <cassert>
#include <charconv>
#include <optional>
#include <string_view>
std::optional<int> parse(std::string_view sv, int base, std::string_view prefix = "")
{
if (!prefix.empty() && !sv.starts_with(prefix))
return std::nullopt;
int n{};
auto [ptr, ec] = std::from_chars(sv.data() + prefix.size(), sv.data() + sv.size(), n, base);
if (ec == std::errc{} && ptr == sv.data() + sv.size())
return n;
else
return std::nullopt;
}
std::optional<int> parse_digit(std::string_view sv)
{
return parse(sv, 2, "0b")
.or_else([sv] { return parse(sv, 10); })
.or_else([sv] { return parse(sv, 16, "0x"); });
}
int main()
{
assert(parse_digit("0b11") == std::optional(3));
assert(parse_digit("11") == std::optional(11));
assert(parse_digit("0x11") == std::optional(17));
assert(parse_digit("x") == std::nullopt);
}
出力
バージョン
言語
- C++23
処理系
- Clang: ??
- GCC: ??
- ICC: ??
- Visual C++: ??