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
См. также
|
(C++17) | считывает значение variant по индексу или типу (если тип уникален); при ошибке выбрасывает исключение (шаблон функции) |
возвращает индекс, начинающийся с нуля, альтернативы, содержащейся в variant (открытая функция-член) |
|
|
(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