Section

std::variant

The class template std::variant represents a type-safe union: one object that can hold exactly one value from a fixed set of alternative types. At any moment it either contains one alternative, or it is temporarily in the invalid valueless_by_exception state after an exception during a type-changing operation.

Unlike many dynamic sum-type wrappers, a variant stores its active object directly inside the variant itself and does not perform separate dynamic allocation. The alternatives must therefore be object types that satisfy the usual destruction requirements.

std::variant is a good fit when the set of possible result types is known at compile time and callers should be forced to handle each alternative explicitly.

# Declarations

template< class... Types >
class variant;

(since C++17)

# Template parameters

  • Types...: the alternative types that may be stored in the variant. Every alternative must satisfy the Destructible requirements. References, arrays, and void are not allowed as alternatives.

# Semantics

  • A variant always has at most one active alternative.
  • A default-constructed variant initializes its first alternative. If the first alternative is not default-constructible, the variant is not default-constructible either.
  • std::monostate is commonly used as the first alternative when a meaningful empty/default state is needed.
  • The same type may appear more than once in Types...; index-based access remains valid, but type-based access requires the type to be unique.
  • Instantiating std::variant<> with no alternatives is ill-formed.

# Member functions

# Special members

# Observers

# Modifiers

# Visitation

  • variant::visit: C++26 member visitation for invoking a callable with the active alternative

# Non-member functions

  • visit: applies a callable to the active alternatives from one or more variant objects
  • holds_alternative: checks whether a variant currently holds a given unique type
  • get: accesses the contained value by index or by unique type and throws on mismatch
  • get_if: returns a pointer to the contained value by index or unique type, or nullptr on mismatch
  • operator==, !=, <, <=, >, >=, <=>: compares variant objects through their active alternatives
  • std::swap: specialization for swapping variant objects

# Helper classes

# Helper objects

  • variant_npos: sentinel index used when a variant is valueless

# Notes

Feature-test macroValueStdFeature
__cpp_lib_variant201606LC++17std::variant: type-safe union
__cpp_lib_variant202102LC++23 (DR17)std::visit supports classes derived from std::variant
__cpp_lib_variant202106LC++23 (DR20)fully constexpr std::variant
__cpp_lib_variant202306LC++26member 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);

    w = std::get<int>(v);
    w = std::get<0>(v); // same effect as the previous line
    w = v;

//  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
    }
    catch (const std::bad_variant_access& ex)
    {
        std::cout << ex.what() << '\n';
    }

    using namespace std::literals;

    std::variant<std::string> x("abc");
    x = "def"; // converting assignment works when unambiguous

    std::variant<std::string, void const*> y("abc");
    assert(std::holds_alternative<void const*>(y));
    y = "xyz"s;
    assert(std::holds_alternative<std::string>(y));
}

Possible output:

std::get: wrong index for variant

# Defect reports

DRApplied toBehavior as publishedCorrect behavior
LWG 2901C++17std::uses_allocator specialization was provided even though std::variant cannot properly support allocatorsspecialization removed
LWG 3990C++17a program could declare an explicit or partial specialization of std::variantthe program is ill-formed in that case, with no diagnostic required

# See also