std::variant

From cppreference.com
< cpp‎ | utility
 
 
Utilities library
General utilities
Relational operators (deprecated in C++20)
 
 
Defined in header <variant>
template< class... Types >
class variant;
(since C++17)

The class template std::variant represents a type-safe union. An instance of std::variant at any given time either holds a value of one of its alternative types, or in the case of error - no value (this state is hard to achieve, see valueless_by_exception).

As with unions, if a variant holds a value of some object type T, the T object is nested within the variant object itself. Variant is not allowed to allocate additional (dynamic) memory.

A variant is not permitted to hold references, arrays, or the type void.

A variant is permitted to hold the same type more than once, and to hold differently cv-qualified versions of the same type.

Consistent with the behavior of unions during aggregate initialization, a default-constructed variant holds a value of its first alternative, unless that alternative is not default-constructible (in which case the variant is not default-constructible either). The helper class std::monostate can be used to make such variants default-constructible.

A program that instantiates the definition of std::variant with no template arguments is ill-formed. std::variant<std::monostate> can be used instead.

If a program declares an explicit or partial specialization of std::variant, the program is ill-formed, no diagnostic required.

Template parameters

Types - the types that may be stored in this variant. All types must meet the Destructible requirements (in particular, array types and non-object types are not allowed).

Member functions

constructs the variant object
(public member function)
destroys the variant, along with its contained value
(public member function)
assigns a variant
(public member function)
Observers
returns the zero-based index of the alternative held by the variant
(public member function)
checks if the variant is in the invalid state
(public member function)
Modifiers
constructs a value in the variant, in place
(public member function)
swaps with another variant
(public member function)
Visitation
(C++26)
calls the provided functor with the argument held by the variant
(public member function)

Non-member functions

(C++17)
calls the provided functor with the arguments held by one or more variants
(function template)
checks if a variant currently holds a given type
(function template)
reads the value of the variant given the index or the type (if the type is unique), throws on error
(function template)
(C++17)
obtains a pointer to the value of a pointed-to variant given the index or the type (if unique), returns null on error
(function template)
(C++17)(C++17)(C++17)(C++17)(C++17)(C++17)(C++20)
compares variant objects as their contained values
(function template)
specializes the std::swap algorithm
(function template)

Helper classes

(C++17)
placeholder type for use as the first alternative in a variant of non-default-constructible types
(class)
exception thrown on invalid accesses to the value of a variant
(class)
obtains the size of the variant's list of alternatives at compile time
(class template) (variable template)
obtains the type of the alternative specified by its index, at compile time
(class template) (alias template)
hash support for std::variant
(class template specialization)

Helper objects

index of the variant in the invalid state
(constant)

Notes

Feature-test macro Value Std Feature
__cpp_lib_variant 201606L (C++17) std::variant: a type-safe union
202102L (C++17)
(DR)
std::visit for classes derived from std::variant
202106L (C++20)
(DR)
Fully constexpr std::variant
202306L (C++26) Member visit

Example

#include <cassert>
#include <iostream>
#include <string>
#include <variant>
 
int main()
{
    std::variant<int, float> v, w;
    v = 42; // v contains int
    int i = std::get<int>(v);
    assert(42 == i); // succeeds
    w = std::get<int>(v);
    w = std::get<0>(v); // same effect as the previous line
    w = v; // same effect as the previous line
 
//  std::get<double>(v); // error: no double in [int, float]
//  std::get<3>(v);      // error: valid index values are 0 and 1
 
    try
    {
        std::get<float>(w); // w contains int, not float: will throw
    }
    catch (const std::bad_variant_access& ex)
    {
        std::cout << ex.what() << '\n';
    }
 
    using namespace std::literals;
 
    std::variant<std::string> x("abc");
    // converting constructors work when unambiguous
    x = "def"; // converting assignment also works when unambiguous
 
    std::variant<std::string, void const*> y("abc");
    // casts to void const* when passed a char const*
    assert(std::holds_alternative<void const*>(y)); // succeeds
    y = "xyz"s;
    assert(std::holds_alternative<std::string>(y)); // succeeds
}

Possible output:

std::get: wrong index for variant

Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior
LWG 2901 C++17 specialization of std::uses_allocator provided,
but std::variant cannot properly support allocators
specialization removed
LWG 3990 C++17 a program could declare an explicit or
partial specialization of std::variant
the program is ill-formed in this
case (no diagnostic required)

See also

in-place construction tag
(tag)
(C++17)
a wrapper that may or may not hold an object
(class template)
(C++17)
objects that hold instances of any CopyConstructible type
(class)