Пространства имён
Варианты
Действия

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

Материал из cppreference.com
< cpp‎ | utility‎ | variant
 
 
Библиотека утилит
Языковая поддержка
Поддержка типов (базовые типы, RTTI)
Макросы тестирования функциональности библиотеки (C++20)    
Управление динамической памятью
Программные утилиты
Поддержка сопрограмм (C++20)
Вариативные функции
Трёхстороннее сравнение (C++20)
(C++20)
(C++20)(C++20)(C++20)(C++20)(C++20)(C++20)
Общие утилиты
Дата и время
Функциональные объекты
Библиотека форматирования (C++20)
(C++11)
Операторы отношения (устарело в C++20)
Целочисленные функции сравнения
(C++20)(C++20)(C++20)    
(C++20)
Операции обмена и типа
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
Общие лексические типы
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)
(C++23)
Элементарные преобразования строк
(C++17)
(C++17)
 
 
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

[править] Смотрите также

читает значение variant по заданному индексу или типу (если тип уникален), генерирует исключение при ошибке
(шаблон функции) [править]
возвращает отсчитываемый от нуля индекс альтернативы, удерживаемой variant
(public функция-элемент) [править]
исключение при неправильном доступе к значению variant
(класс) [править]