最終更新日時(UTC):
が更新

履歴 編集

function
<expected>

std::expected::コンストラクタ(C++23)

constexpr expected();                                   // (1)
constexpr expected(const expected& rhs);                // (2)
constexpr expected(expected&& rhs) noexcept(see below); // (3)

template<class U, class G>
constexpr explicit(see below) expected(const expected<U, G>& rhs); // (4)
template<class U, class G>
constexpr explicit(see below) expected(expected<U, G>&& rhs);      // (5)

template<class U = T>
constexpr explicit(see below) expected(U&& v);      // (6)

template<class G>
constexpr explicit(see below) expected(const unexpected<G>& e); // (7)
template<class G>
constexpr explicit(see below) expected(unexpected<G>&& e);      // (8)

template<class... Args>
constexpr explicit expected(in_place_t, Args&&... args); // (9)
template<class U, class... Args>
constexpr explicit expected(in_place_t, initializer_list<U> il, Args&&... args); // (10)

template<class... Args>
constexpr explicit expected(unexpect_t, Args&&... args); // (11)
template<class U, class... Args>
constexpr explicit expected(unexpect_t, initializer_list<U> il, Args&&... args); // (12)

概要

  • (1) : 正常値型T値初期化して保持する。
  • (2) : コピーコンストラクタ。
  • (3) : ムーブコンストラクタ。
  • (4) : 変換可能なexpectedオブジェクトからコピー構築する。
  • (5) : 変換可能なexpectedオブジェクトからムーブ構築する。
  • (6) : 正常値型Tに変換可能な型Uの値を正常値として受け取り、コピーまたはムーブして保持する。
  • (7) : 変換可能なunexpectedオブジェクトかエラー値をコピー構築する。
  • (8) : 変換可能なunexpectedオブジェクトからエラー値をムーブ構築する。
  • (9) : 正常値型Tのコンストラクタ引数として任意個の引数を受け取って、コンストラクタ内で型Tのオブジェクトを正常値として生成し、保持する。
  • (10) : 正常値型Tのコンストラクタ引数として初期化子リストと任意個の引数を受け取って、コンストラクタ内で型Tのオブジェクトを正常値として生成し、保持する。
  • (11) : エラー値型Eのコンストラクタ引数として任意個の引数を受け取って、コンストラクタ内で型Eのオブジェクトをエラー値として生成し、保持する。
  • (12) : エラー値型Eのコンストラクタ引数として初期化子リストと任意個の引数を受け取って、コンストラクタ内で型Eのオブジェクトをエラー値として生成し、保持する。

説明用のテンプレート変数converts-from-any-cvrefを次の通り定義する。

template<class T, class W>
constexpr bool converts-from-any-cvref =
  disjunction_v<is_constructible<T, W&>, is_convertible<W&, T>,
                is_constructible<T, W>, is_convertible<W, T>,
                is_constructible<T, const W&>, is_convertible<const W&, T>,
                is_constructible<T, const W>, is_convertible<const W, T>>;

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

効果

事後条件

  • (1) : 正常値を保持している。
  • (2) : rhsが正常値を保持する場合は*thisも正常値を保持し、rhsがエラー値を保持する場合は*thisもエラー値を保持する。
  • (3) : rhsが正常値を保持する場合は*thisも正常値を保持し、rhsがエラー値を保持する場合は*thisもエラー値を保持する。rhs.has_value()は変化しない。
  • (4), (5) : rhsが正常値を保持する場合は*thisも正常値を保持し、rhsがエラー値を保持する場合は*thisもエラー値を保持する。rhs.has_value()は変化しない。
  • (6) : 正常値を保持している。
  • (7), (8) : エラー値を保持している。
  • (9), (10) : 正常値を保持している。
  • (11), (12) : エラー値を保持している。

例外

  • (1) : 正常値型の初期化から送出される例外。
  • (2) : 正常値型またはエラー値型の初期化から送出される例外。
  • (3) : 正常値型またはエラー値型の初期化から送出される例外。
  • (4), (5) : 正常値型またはエラー値型の初期化から送出される例外。
  • (6) : 正常値型の初期化から送出される例外。
  • (7), (8) : エラー値型の初期化から送出される例外。
  • (9), (10) : 正常値型の初期化から送出される例外。
  • (11), (12) : エラー値型の初期化から送出される例外。

delete定義される条件

トリビアルに定義される条件

explicitになる条件

#include <cassert>
#include <expected>
#include <memory>
#include <string>
#include <string_view>
#include <tuple>
#include <utility>
#include <vector>

// std::pair型から2要素std::tuple型へはコピー変換可能
using IntPair  = std::pair<int, int>;
using IntTuple = std::tuple<int, int>;

// std::unique_ptr型からstd::shared_ptr型へはムーブ変換可能
using UniquePtr = std::unique_ptr<int>;
using SharedPtr = std::shared_ptr<int>;

// 引数リスト または 初期化子リスト+引数リスト から構築可能な型
struct ComplexType {
  std::string data;
  std::vector<int> seq;

  ComplexType(const char* ptr, size_t len)
    : data(ptr, len) {}
  ComplexType(std::initializer_list<int> il, std::string_view sv)
    : data(sv), seq(il) {} 
};

int main()
{
  // (1) デフォルトコンストラクタ
  {
    std::expected<int, std::string> x;
    assert(x.has_value());
    assert(x.value() == 0);
    // int型の値初期化{}は値0
  }

  // (2) コピーコンストラクタ
  {
    std::expected<int, std::string> srcV = 42;
    std::expected<int, std::string> dstV = srcV;
    assert(srcV.has_value() && dstV.has_value());
    assert(srcV.value() == 42 && dstV.value() == 42);

    std::expected<int, std::string> srcE = std::unexpected{"Oops"};
    std::expected<int, std::string> dstE = srcE;
    assert(!srcE.has_value() && !dstE.has_value());
    assert(srcE.error() == "Oops" && dstE.error() == "Oops");
  }

  // (3) ムーブコンストラクタ
  {
    std::expected<std::string, int> srcV = "ok";
    std::expected<std::string, int> dstV = std::move(srcV);
    assert(srcV.has_value() && dstV.has_value());
    assert(dstV.value() == "ok");
    // srcV.value()std::stringムーブ後の未規定の値

    std::expected<int, std::string> srcE = std::unexpected{"ng"};
    std::expected<int, std::string> dstE = std::move(srcE);
    assert(!srcE.has_value() && !dstE.has_value());
    assert(dstE.error() == "ng");
    // srcE.error()std::stringムーブ後の未規定の値
  }

  // (4) 変換コピー構築
  {
    std::expected<IntPair,  int> src = IntPair{1, 2};
    std::expected<IntTuple, int> dst = src;
    assert(src.has_value() && dst.has_value());
    assert((dst.value() == IntTuple{1, 2}));
  }

  // (5) 変換ムーブ構築
  {
    std::expected<UniquePtr, int> src = std::make_unique<int>(42);
    std::expected<SharedPtr, int> dst = std::move(src);
    assert(src.has_value() && dst.has_value());
    assert(*dst.value() == 42);
    assert(src.value() == nullptr);
    // ムーブ後のstd::unique_ptr型はnullptrが保証される
  }

  // (6) 正常値の変換コピー/ムーブ構築
  {
    IntPair src1{1, 2};
    std::expected<IntTuple, int> dst1 = src1;
    assert(dst1.has_value());
    assert((dst1.value() == IntTuple{1, 2}));

    UniquePtr src2 = std::make_unique<int>(42);
    std::expected<SharedPtr, int> dst2 = std::move(src2);
    assert(dst2.has_value());
    assert(*dst2.value() == 42);
  }

  // (7),(8) エラー値の変換コピー/ムーブ構築
  {
    std::unexpected<IntPair> src1{std::in_place, 1, 2};
    std::expected<int, IntTuple> dst1 = src1;
    assert(not dst1.has_value());
    assert((dst1.error() == IntTuple{1, 2}));

    UniquePtr src2 = std::make_unique<int>(42);
    std::expected<int, SharedPtr> dst2 = std::unexpected{std::move(src2)};
    assert(not dst2.has_value());
    assert(*dst2.error() == 42);
  }

  // (9),(10) 引数リストから正常値を直接構築
  {
    std::expected<ComplexType, int> x1{std::in_place, "C++", 1};
    assert(x1.has_value());
    assert(x1.value().data == "C");
    // "C++"より長さ1の文字列が構築されている

    std::expected<ComplexType, int> x2{std::in_place, {5, 6, 7, 8}, "Steps"};
    assert(x2.has_value());
    assert(x2.value().data == "Steps");
    assert((x2.value().seq == std::vector<int>{5, 6, 7, 8}));
  }

  // (11),(12) 引数リストからエラー値を直接構築
  {
    std::expected<int, ComplexType> x1{std::unexpect, "Hello!", 4};
    assert(not x1.has_value());
    assert(x1.error().data == "Hell");
    // "Hello!"より長さ4の文字列が構築されている

    std::expected<int, ComplexType> x2{std::unexpect, {1, 2, 3}, "Lotus"};
    assert(not x2.has_value());
    assert(x2.error().data == "Lotus");
    assert((x2.error().seq == std::vector<int>{1, 2, 3}));
  }
}

出力

バージョン

言語

  • C++23

処理系

参照