std::variant<Types...>::valueless_by_exception
Материал из cppreference.com
<tbody>
</tbody>
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 может потерять значение
variant, который потерял значение в результате исключения, рассматривается как находящийся в недопустимом состоянии: 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("конструктор копирования"); }
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) Исключение: " << ex.what() << '\n';
}
assert(var.index() == std::variant_npos);
assert(var.valueless_by_exception() == true);
// Теперь переменная "не имеет значения", что является недопустимым состоянием,
// вызванным исключением, сгенерированным в процессе присваивания изменения типа
try {
std::get<1>(var);
} catch (const std::bad_variant_access& ex) {
std::cout << "2) Исключение: " << ex.what() << '\n';
}
var = "str2";
assert(var.index() == 0);
assert(std::get<0>(var) == "str2");
assert(var.valueless_by_exception() == false);
}
Возможный вывод:
1) Исключение: конструктор копирования
2) Исключение: std::get: variant is valueless
Смотрите также
(C++17) |
читает значение variant по заданному индексу или типу (если тип уникален), генерирует исключение при ошибке (шаблон функции) |
| возвращает отсчитываемый от нуля индекс альтернативы, удерживаемой variant (public функция-элемент) | |
(C++17) |
исключение при неправильном доступе к значению variant (класс) |