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

From cppreference.com
< cpp‎ | utility‎ | variant
 
 
Utilities library
General utilities
Date and time
Function objects
Formatting library (C++20)
(C++11)
Relational operators (deprecated in C++20)
Integer comparison functions
(C++20)
Swap and type operations
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
Common vocabulary types
(C++11)
(C++17)
(C++17)
(C++17)
(C++17)

Elementary string conversions
(C++17)
(C++17)
 
 
constexpr bool valueless_by_exception() const noexcept;
(since C++17)

Returns false if and only if the variant holds a value.

Notes

A variant may become valueless in the following situations:

  • (guaranteed) an exception is thrown during the move initialization of the contained value from the temporary in copy assignment
  • (guaranteed) an exception is thrown during the move initialization of the contained value during move assignment
  • (optionally) an exception is thrown when initializing the contained value during a type-changing assignment
  • (optionally) an exception is thrown when initializing the contained value during a type-changing emplace

Since variant is never permitted to allocate dynamic memory, previous value cannot be retained in these situations.

This applies even to variants of non-class types:

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

A variant that is valueless by exception is treated as being in an invalid state: index returns variant_npos, get and visit throw bad_variant_access.

Example

#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{666};
    } 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 var's initialization.
 
    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);
}

Possible output:

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

See also

reads the value of the variant given the index or the type (if the type is unique), throws on error
(function template)
returns the zero-based index of the alternative held by the variant
(public member function)
exception thrown on invalid accesses to the value of a variant
(class)