Namespaces
Variants

std::variant<Types...>:: valueless_by_exception

From cppreference.net
Utilities library
constexpr bool valueless_by_exception ( ) const noexcept ;
(C++17以降)

バリアントが値を保持している場合に限り、 false を返します。

注記

バリアントは、以下の状況で含まれる値の初期化中に無効値になる可能性があります:

  • (保証) 例外が ムーブ代入 中にスローされる
  • (オプション) 例外が コピー代入 中にスローされる
  • (オプション) 例外が型変更 代入 中にスローされる
  • (オプション) 例外が型変更 emplace 中にスローされる

variantは動的メモリの確保を決して許可されないため、これらの状況では以前の値を保持し、したがって復元することはできません。「optional」の場合、型が例外を投げないムーブを提供し、実装が最初にスタック上で新しい値を構築し、その後variantにムーブする場合、例外の送出を回避できます。

これは非クラス型のバリアントに対しても適用されます:

struct S
{
    operator int() { throw 42; }
};
std::variant<float, int> v{12.f}; // OK
v.emplace<1>(S()); // vは値を持たない状態になる可能性あり

例外によって値を持たないバリアント — つまり、上記の状況のいずれかで以前に発生した例外によって値がなくなったもの — は、無効な状態にあるものとして扱われます:

  • index variant_npos を返す
  • get bad_variant_access を送出する
  • visit および メンバー visit (C++26以降) bad_variant_access を送出する

#include <cassert>
#include <iostream>
#include <stdexcept>
#include <string>
#include <variant>
struct Demo
{
    Demo(int) {}
    Demo(const Demo&) { throw std::domain_error("copy ctor"); }
    Demo& operator= (const Demo&) = default;
};
int main()
{
    std::variant<std::string, Demo> var{"str"};
    assert(var.index() == 0);
    assert(std::get<0>(var) == "str");
    assert(var.valueless_by_exception() == false);
    try
    {
        var = Demo{555};
    {
    catch (const std::domain_error& ex)
    {
        std::cout << "1) Exception: " << ex.what() << '\n';
    }
    assert(var.index() == std::variant_npos);
    assert(var.valueless_by_exception() == true);
    // 現在、varは「valueless」状態であり、これは型変更代入の過程で例外が発生したことによる無効な状態です
    try
    {
        std::get<1>(var);
    }
    catch (const std::bad_variant_access& ex)
    {
        std::cout << "2) Exception: " << ex.what() << '\n';
    }
    var = "str2";
    assert(var.index() == 0);
    assert(std::get<0>(var) == "str2");
    assert(var.valueless_by_exception() == false);
}

出力例:

1) Exception: copy ctor
2) Exception: std::get: variant is valueless

関連項目

インデックスまたは型(型が一意の場合)を指定してvariantの値を読み取り、エラー時に例外をスロー
(関数テンプレート)
variant が保持している代替値の0から始まるインデックスを返す
(公開メンバ関数)
variant の値への不正なアクセス時にスローされる例外
(クラス)