Namespaces
Variants

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

From cppreference.net
Utilities library
constexpr bool valueless_by_exception ( ) const noexcept ;
(seit C++17)

Gibt false genau dann zurück, wenn der Variant keinen Wert enthält.

Hinweise

Ein Variant kann in den folgenden Situationen wertlos werden, wenn der enthaltene Wert initialisiert wird:

  • (garantiert) eine Exception wird während der Move-Zuweisung geworfen
  • (optional) eine Exception wird während der Kopierzuweisung geworfen
  • (optional) eine Exception wird während einer typändernden Zuweisung geworfen
  • (optional) eine Exception wird während einer typändernden emplace Operation geworfen

Da variant niemals dynamischen Speicher allozieren darf, kann der vorherige Wert in diesen Situationen nicht beibehalten und daher nicht wiederhergestellt werden. Die "optional"-Fälle können das Werfen einer Exception vermeiden, wenn der Typ nicht-werfende Moves bereitstellt und die Implementierung zuerst den neuen Wert auf dem Stack konstruiert und ihn dann in das variant verschiebt.

Dies gilt auch für Varianten von Nicht-Klassentypen:

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

Eine Variante, die valueless by exception ist — das heißt, aufgrund einer vorherigen Ausnahme aus einer der oben aufgeführten Situationen keinen Wert hat — wird als in einem ungültigen Zustand befindlich behandelt:

Beispiel

#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);
    // Jetzt ist var "wertlos", was ein ungültiger Zustand ist, verursacht
    // durch eine Ausnahme während der typändernden Zuweisung.
    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);
}

Mögliche Ausgabe:

1) Exception: copy ctor
2) Exception: std::get: variant is valueless

Siehe auch

liest den Wert des Varianten anhand des Index oder des Typs (falls der Typ eindeutig ist), wirft bei Fehler
(Funktions-Template)
gibt den nullbasierten Index der Alternative zurück, die von der variant gehalten wird
(öffentliche Member-Funktion)
Ausnahme, die bei ungültigen Zugriffen auf den Wert einer variant geworfen wird
(Klasse)