Spec-Zone.ru › C++

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

constexpr bool valueless_by_exception() const noexcept;
(начиная с C++17)

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

Примечания

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

  • (гарантированно) во время перемещающего присваивания выбрасывается исключение
  • (возможно) во время копирующего присваивания выбрасывается исключение
  • (возможно) во время меняющего тип присваивания выбрасывается исключение
  • (возможно) во время меняющего тип emplace выбрасывается исключение

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

Это относится даже к вариантам с типами, не являющимися классами:

struct S
{
    operator int() { throw 42; }
};
std::variant<float, int> v{12.f}; // OK
v.emplace<1>(S()); // v may be valueless

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

  • 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);

    // Now the var is "valueless" which is an invalid state caused
    // by an exception raised in the process of type-changing assignment.

    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

См. также

get(std::variant)
(C++17)
считывает значение variant по индексу или типу (если тип уникален); при ошибке выбрасывает исключение
(шаблон функции)
index
возвращает индекс, начинающийся с нуля, альтернативы, содержащейся в variant
(открытая функция-член)
bad_variant_access
(C++17)
исключение, выбрасываемое при недопустимом доступе к значению variant
(класс)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/utility/variant/valueless_by_exception

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API