Skip to content

Latest commit

 

History

History
173 lines (136 loc) · 4.85 KB

File metadata and controls

173 lines (136 loc) · 4.85 KB

or_else

  • optional[meta header]
  • function template[meta id-type]
  • std[meta namespace]
  • optional[meta class]
  • cpp23[meta cpp]
// optional<T>版のオーバーロード
template<class F> constexpr optional or_else(F&& f) const &; // (1) C++23
template<class F> constexpr optional or_else(F&& f) &&;      // (2) C++23

// optional<T&>版のオーバーロード (C++26)
template<class F> constexpr optional or_else(F&& f) const;   // (3) C++26

概要

有効値を保持していれば、なにもしない。 有効値を保持していなければ、f()の呼び出し結果をoptionalとして返す。

  • (1) : *thisconst左辺値の場合
  • (2) : *thisが右辺値の場合
  • (3) : optional<T&>の場合

optional<T>では (1), (2) が定義され、optional<T&>では (3) のみが定義される。

実際には複数オーバーロードが提供されるが、大まかには下記シグニチャのようにみなせる。 or_elseへは、空の引数リストをとりstd::optional<T>へ変換可能なReturn型を返す関数や関数オブジェクトを与える。

template <class T>
class optional {
  template <class Return>
  std::optional<T> or_else(function<Return()> func);
};
  • function[link /reference/functional/function.md]

テンプレートパラメータ制約

適格要件

is_same_v<remove_cvref_t<invoke_result_t<F>>, optional>trueであること

効果

  • (1), (3) : 次と等価

    if (*this) {
      return *this;
    } else {
      return std::forward<F>(f)();
    }
  • (2) : 次と等価

    if (*this) {
      return std::move(*this);
    } else {
      return std::forward<F>(f)();
    }
    • std::move[link /reference/utility/move.md]

備考

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);
}
  • or_else[color ff0000]
  • std::nullopt[link ../nullopt_t.md]
  • value()[link value.md]

出力

メソッドチェインとしての使い方

#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);
}
  • or_else[color ff0000]
  • std::nullopt[link ../nullopt_t.md]
  • std::from_chars[link ../../charconv/from_chars.md]
  • std::errc[link ../../system_error/errc.md]
  • prefix.empty()[link /reference/string_view/basic_string_view/empty.md]
  • prefix.size()[link /reference/string_view/basic_string_view/size.md]
  • sv.starts_with[link /reference/string_view/basic_string_view/starts_with.md]

出力

バージョン

言語

  • C++23

処理系

関連項目

参照