Namespaces
Variants

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

From cppreference.net
Utilities library
constexpr bool valueless_by_exception ( ) const noexcept ;
(начиная с C++17)

Возвращает false тогда и только тогда, когда вариант содержит значение.

Примечания

Вариант может стать бесполезным при инициализации содержащегося значения в следующих ситуациях:

  • (гарантированно) исключение выбрасывается во время move assignment
  • (опционально) исключение выбрасывается во время copy assignment
  • (опционально) исключение выбрасывается во время type-changing assignment
  • (опционально) исключение выбрасывается во время type-changing emplace

Поскольку variant никогда не разрешает выделять динамическую память, предыдущее значение не может быть сохранено и, следовательно, восстановлено в этих ситуациях. Случаи с "optional" могут избежать выбрасывания исключения, если тип предоставляет не выбрасывающие исключения перемещения и реализация сначала конструирует новое значение в стеке, а затем перемещает его в variant.

Это применимо даже к вариантам неклассовых типов:

struct S
{
    operator int() { throw 42; }
};
std::variant<float, int> v{12.f}; // OK
v.emplace<1>(S()); // v может оказаться без значения

Вариант, который является бесценностным по исключению — то есть не имеет значения из-за предыдущего исключения из одной из перечисленных выше ситуаций — рассматривается как находящийся в недопустимом состоянии:

Пример

#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 находится в состоянии "без значения" - недопустимом состоянии,
    // вызванном исключением в процессе присваивания с изменением типа.
    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
(класс)