< cpp‎ | utility
Utilities library
General utilities
Date and time
Function objects
Formatting library (C++20)
Relational operators (deprecated in C++20)
Integer comparison functions
Swap and type operations
Common vocabulary types
Elementary string conversions
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 object representation of T is allocated directly within the object representation of the variant itself. Variant is not allowed to allocate additional (dynamic) memory.

A variant is not permitted to hold references, arrays, or the type void. Empty variants are also ill-formed (std::variant<std::monostate> can be used instead).

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.

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)
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)
constructs a value in the variant, in place
(public member function)
swaps with another variant
(public member function)

Non-member functions

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)
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)
compares variant objects as their contained values
(function template)
specializes the std::swap algorithm
(function template)

Helper classes

placeholder type for use as the first alternative in a variant of non-default-constructible types
exception thrown on invalid accesses to the value of a variant
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)
specializes the std::hash algorithm
(class template specialization)

Helper objects

index of the variant in the invalid state


Feature-test macro: __cpp_lib_variant


#include <variant>
#include <string>
#include <cassert>
#include <iostream>
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 variant can't
properly support allocators
specialization removed

See also

in-place construction tag
(class template)
a wrapper that may or may not hold an object
(class template)
Objects that hold instances of any CopyConstructible type.