Spec-Zone.ru › C++

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

constexpr bool valueless_by_exception() const noexcept;
(с C++17)

Возвращает false тогда и только тогда, когда переменная хранит значение.

Примечания

Переменная может стать бесценной в следующих ситуациях:

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

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

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

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

Переменная, которая является бесценной из-за исключения, рассматривается как находящаяся в недопустимом состоянии: index возвращает variant_npos, get и visit выбрасывают 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)
считывает значение переменной, заданное индексом или типом (если тип уникален), выбрасывает ошибку
(шаблон функции)
index
возвращает индекс (с нуля) альтернативы, содержащейся в переменной
(публичный член-функция)
bad_variant_access
(C++17)
исключение, выбрасываемое при недопустимом доступе к значению переменной
(класс)

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

Spec-Zone.ru

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