最終更新日時: 2024年06月11日 22時45分38秒 (JST)
Akira Takahashi が更新

履歴 編集

function
<variant>

# std::variant::valueless_by_exception(C++17)

    constexpr bool valueless_by_exception() const noexcept;

## 概要

例外によって値を持たない状態になっているかを判定する。

このクラスは、保持する型と値を切り替える代入操作をする際に例外が発生した場合、元の状態には戻さず空になる可能性がある (必ず空になるわけではない)。そのような状況で空になっていることを、本関数で判定できる。

## 戻り値

有効な値を保持している場合は`false`を返し、そうでない場合は`true`を返す。

## 備考

- このクラスの元となったBoost Variant Libraryの`variant`クラスは、「決して空にならない保証 ("Never-Empty" Guarantee)」をもっているが、本クラスにはそのような保証がないため、新たな型の代入操作で例外が発生した場合に空になる可能性がある
- `variant<int, float>`のように直接的に例外を送出しない型のみの場合でも、`emplace()`操作で例外が送出される可能性がある：

      struct S { operator int() { throw 42; }};
      variant<float, int> v = 12.f;
      try {
        v.emplace<1>(S());
      }
      catch (...) {
        if (v.valueless_by_exception()) {
          // …
        }
      }

## 例

    #include <iostream>
    #include <cassert>
    #include <variant>

    struct AlwaysThrow {
      AlwaysThrow() = default;

      AlwaysThrow(const AlwaysThrow&) {
        throw std::exception();
      }

      AlwaysThrow(AlwaysThrow&&) {
        throw std::exception();
      }

      AlwaysThrow& operator=(const AlwaysThrow&) {
        throw std::exception();
      }

      AlwaysThrow& operator=(AlwaysThrow&&) {
        throw std::exception();
      }
    };

    int main()
    {
      std::variant<int, AlwaysThrow> v = 0;

      try {
        assert(!v.valueless_by_exception());

        v = AlwaysThrow{}; // 例外発生
        assert(false);
      }
      catch (...) {
        // vが空になる可能性がある
        if (v.valueless_by_exception()) {
          std::cout << "empty" << std::endl;
          assert(v.index() == std::variant_npos);
        }
        else {
          std::cout << "not empty" << std::endl;
        }
      }
    }

### 出力例

    empty

## バージョン

### 言語

- C++17

### 処理系

- Clang: 4.0.1 ✅
- GCC: 7.3 ✅
- Visual C++: ??