Author: Peter Dimov

# Boost.Variant2: A never valueless variant type

Peter Dimov

## Overview

### Description

This library implements a type-safe discriminated/tagged union type, `variant<T…​>`, that is API-compatible with the C++17 Standard’s `std::variant<T…​>`.

A `variant<T1, T2, …​, Tn>` variable can hold a value of any of the types `T1`, `T2`, …​, `Tn`. For example, `variant<int64_t, double, std::string>` can hold an `int64_t` value, a `double` value, or a `string` value.

Such a type is sometimes called a "tagged union", because it’s roughly equivalent to

    struct V
    {
        enum tag { tag_int64_t, tag_double, tag_string };

        tag tag_;

        union
        {
            int64_t     i_;
            double      d_;
            std::string s_;
        };
    };

### Usage Examples

Variants can be used to represent dynamically-typed values. A configuration file of the form

    server.host=test.example.com
    server.port=9174
    cache.max_load=0.7

can be represented as `std::map<std::string, variant<int64_t, double, std::string>>`.

Variants can also represent polymorphism. To take a classic example, a polymorphic collection of shapes:

    #define _USE_MATH_DEFINES
    #include <iostream>
    #include <vector>
    #include <memory>
    #include <cmath>

    class Shape
    {
    public:

        virtual ~Shape() = default;
        virtual double area() const = 0;
    };

    class Rectangle: public Shape
    {
    private:

        double width_, height_;

    public:

        Rectangle( double width, double height ):
            width_( width ), height_( height ) {}

        virtual double area() const { return width_ * height_; }
    };

    class Circle: public Shape
    {
    private:

        double radius_;

    public:

        explicit Circle( double radius ): radius_( radius ) {}
        virtual double area() const { return M_PI * radius_ * radius_; }
    };

    double total_area( std::vector<std::unique_ptr<Shape>> const & v )
    {
        double s = 0.0;

        for( auto const& p: v )
        {
            s += p->area();
        }

        return s;
    }

    int main()
    {
        std::vector<std::unique_ptr<Shape>> v;

        v.push_back( std::unique_ptr<Shape>( new Circle( 1.0 ) ) );
        v.push_back( std::unique_ptr<Shape>( new Rectangle( 2.0, 3.0 ) ) );

        std::cout << "Total area: " << total_area( v ) << std::endl;
    }

can instead be represented as a collection of `variant<Rectangle, Circle>` values. This requires the possible `Shape` types be known in advance, as is often the case. In return, we no longer need virtual functions, or to allocate the values on the heap with `new Rectangle` and `new Circle`:

    #define _USE_MATH_DEFINES
    #include <iostream>
    #include <vector>
    #include <cmath>

    #include <boost/variant2/variant.hpp>
    using namespace boost::variant2;

    struct Rectangle
    {
        double width_, height_;
        double area() const { return width_ * height_; }
    };

    struct Circle
    {
        double radius_;
        double area() const { return M_PI * radius_ * radius_; }
    };

    double total_area( std::vector<variant<Rectangle, Circle>> const & v )
    {
        double s = 0.0;

        for( auto const& x: v )
        {
            s += visit( []( auto const& y ){ return y.area(); }, x );
        }

        return s;
    }

    int main()
    {
        std::vector<variant<Rectangle, Circle>> v;

        v.push_back( Circle{ 1.0 } );
        v.push_back( Rectangle{ 2.0, 3.0 } );

        std::cout << "Total area: " << total_area( v ) << std::endl;
    }

### Construction and Assignment

If we look at the

        v.push_back( Circle{ 1.0 } );

line, we can deduce that `variant<Rectangle, Circle>` can be (implicitly) constructed from `Circle` (and `Rectangle`), and indeed it can. It can also be assigned a `Circle` or a `Rectangle`:

    variant<Rectangle, Circle> v = Circle{ 1.0 }; // v holds Circle
    v = Rectangle{ 2.0, 3.0 };                    // v now holds Rectangle

If we try to construct `variant<int, float>` from something that is neither `int` nor `float`, say, `(short)1`, the behavior is "as if" the `variant` has declared two constructors,

    variant::variant(int x);
    variant::variant(float x);

and the standard overload resolution rules are used to pick the one that will be used. So `variant<int, float>((short)1)` will hold an `int`.

### Inspecting the Value

Putting values into a `variant` is easy, but taking them out is necessarily a bit more convoluted. It’s not possible for `variant<int, float>` to define a member function `get() const`, because such a function will need its return type fixed at compile time, and whether the correct return type is `int` or `float` will only become known at run time.

There are a few ways around that. First, there is the accessor member function

    std::size_t variant::index() const noexcept;

that returns the zero-based index of the current type. For `variant<int, float>`, it will return `0` for `int` and `1` for `float`.

Once we have the index, we can use the free function `get<N>` to obtain the value. Since we’re passing the type index to `get`, it knows what to return. `get<0>(v)` will return `int`, and `get<1>(v)` will return `float`:

    void f( variant<int, float> const& v )
    {
        switch( v.index() )
        {
        case 0:

            // use get<0>(v)
            break;

        case 1:

            // use get<1>(v)
            break;

        default:

            assert(false); // never happens
        }
    }

If we call `get<0>(v)`, and `v.index()` is not currently `0`, an exception (of type `bad_variant_access`) will be thrown.

An alternative approach is to use `get<int>(v)` or `get<float>(v)`. This works similarly.

Another alternative that avoids the possibility of `bad_variant_access` is to use `get_if`. Instead of a reference to the contained value, it returns a pointer to it, returning `nullptr` to indicate type mismatch. `get_if` takes a pointer to the `variant`, so in our example we’ll use something along the following lines:

    void f( variant<int, float> const& v )
    {
        if( int const * p = get_if<int>(&v) )
        {
            // use *p
        }
        else if( float const * p = get_if<float>(&v) )
        {
            // use *p
        }
        else
        {
            assert(false); // never happens
        }
    }

### Visitation

Last but not least, there’s `visit`. `visit(f, v)` calls the a function object `f` with the value contained in the `variant` `v` and returns the result. When `v` is `variant<int, float>`, it will call `f` with either an `int` or a `float`. The function object must be prepared to accept both.

In practice, this can be achieved by having the function take a type that can be passed either `int` or `float`, such as `double`:

    double f( double x ) { return x; }

    double g( variant<int, float> const& v )
    {
        return visit( f, v );
    }

By using a function object with an overloaded `operator()`:

    struct F
    {
        void operator()(int x) const { /* use x */ }
        void operator()(float x) const { /* use x */ }
    };

    void g( variant<int, float> const& v )
    {
        visit( F(), v );
    }

Or by using a polymorphic lambda, as we did in our `Circle`/`Rectangle` example:

    void g( variant<int, float> const& v )
    {
        visit( [&]( auto const& x ){ std::cout << x << std::endl; }, v );
    }

`visit` can also take more than one `variant`. `visit(f, v1, v2)` calls `f(x1, x2)`, where `x1` is the value contained in `v1` and `x2` is the value in `v2`.

### Default Construction

The default constructor of `variant` value-initializes the first type in the list. `variant<int, float>{}` holds `0` (of type `int`), and `variant<float, int>{}` holds `0.0f`.

This is usually the desired behavior. However, in cases such as `variant<std::mutex, std::recursive_mutex>`, one might legitimately wish to avoid constructing a `std::mutex` by default. A provided type, `monostate`, can be used as the first type in those scenarios. `variant<monostate, std::mutex, std::recursive_mutex>` will default-construct a `monostate`, which is basically a no-op, as `monostate` is effectively an empty `struct`.

## Revision History

### Changes in 1.78.0

- Added `<boost/variant2.hpp>`.

- Added `unsafe_get<I>`.

- Added `visit_by_index`.

- Added `operator<<`.

### Changes in 1.76.0

- Improved generated code for the double buffered case.

### Changes in 1.74.0

- Added support for derived types in `visit`

- Improved compilation performance for many (hundreds of) alternatives.

- Added support for `visit<R>`

### Changes in 1.73.0

- Added support for `std::hash`, `boost::hash`.

- `variant<T…​>` is now trivial when all types in `T…​` are trivial. This improves performance by enabling it to be passed to, and returned from, functions in registers.

### Changes in 1.71.0

After the Boost formal review, the implementation has been changed to provide the strong exception safety guarantee, instead of basic. `expected` has been removed.

## Design

### Features

This `variant` implementation has two distinguishing features:

- It’s never "valueless", that is, `variant<T1, T2, …​, Tn>` has an invariant that it always contains a valid value of one of the types `T1`, `T2`, …​, `Tn`.

- It provides the strong exception safety guarantee on assignment and `emplace`.

This is achieved with the use of double storage, unless all of the contained types have a non-throwing move constructor.

### Rationale

#### Never Valueless

It makes intuitive sense that `variant<X, Y, Z>` can hold only values of type `X`, type `Y`, or type `Z`, and nothing else.

If we think of `variant` as an extension of `union`, since a `union` has a state called "no active member", an argument can be made that a `variant<X, Y, Z>` should also have such an additional state, holding none of `X`, `Y`, `Z`.

This however makes `variant` less convenient in practice and less useful as a building block. If we really need a variable that only holds `X`, `Y`, or `Z`, the additional empty state creates complications that need to be worked around. And in the case where we do need this additional empty state, we can just use `variant<empty, X, Y, Z>`, with a suitable `struct empty {};`.

From a pure design perspective, the case for no additional empty state is solid. Implementation considerations, however, argue otherwise.

When we replace the current value of the `variant` (of, say, type `X`) with another (of type `Y`), since the new value needs to occupy the same storage as the old one, we need to destroy the old `X` first, then construct a new `Y` in its place. But since this is C++, the construction can fail with an exception. At this point the `variant` is in the "has no active member" state that we’ve agreed it cannot be in.

This is a legitimate problem, and it is this problem that makes having an empty/valueless state so appealing. We just leave the `variant` empty on exception and we’re done.

As explained, though, this is undesirable from a design perspective as it makes the component less useful and less elegant.

There are several ways around the issue. The most straightforward one is to just disallow types whose construction can throw. Since we can always create a temporary value first, then use the move constructor to initialize the one in the `variant`, it’s enough to require a nonthrowing move constructor, rather than all constructors to be nonthrowing.

Unfortunately, under at least one popular standard library implementation, node based containers such as `std::list` and `std::map` have a potentially throwing move constructor. Disallowing `variant<X, std::map<Y, Z>>` is hardly practical, so the exceptional case cannot be avoided.

On exception, we could also construct some other value, leaving the `variant` valid; but in the general case, that construction can also throw. If one of the types has a nonthrowing default constructor, we can use it; but if not, we can’t.

The approach Boost.Variant takes here is to allocate a temporary copy of the value on the heap. On exception, a pointer to that temporary copy can be stored into the `variant`. Pointer operations don’t throw.

Another option is to use double buffering. If our `variant` occupies twice the storage, we can construct the new value in the unused half, then, once the construction succeeds, destroy the old value in the other half.

When `std::variant` was standardized, none of those approaches was deemed palatable, as all of them either introduce overhead or are too restrictive with respect to the types a `variant` can contain. So as a compromise, `std::variant` took a way that can (noncharitably) be described as "having your cake and eating it too."

Since the described exceptional situation is relatively rare, `std::variant` has a special case, called "valueless", into which it goes on exception, but the interface acknowledges its existence as little as possible, allowing users to pretend that it doesn’t exist.

This is, arguably, not that bad from a practical point of view, but it leaves many of us wanting. Rare states that "never" occur are undertested and when that "never" actually happens, it’s usually in the most inconvenient of times.

This implementation does not follow `std::variant`; it statically guarantees that `variant` is never in a valueless state. The function `valueless_by_exception` is provided for compatibility, but it always returns `false`.

Instead, if the contained types are such that it’s not possible to avoid an exceptional situation when changing the contained value, double storage is used.

#### Strong Exception Safety

The initial submission only provided the basic exception safety guarantee. If an attempt to change the contained value (via assignment or `emplace`) failed with an exception, and a type with a nonthrowing default constructor existed among the alternatives, a value of that type was created into the `variant`. The upside of this decision was that double storage was needed less frequently.

The reviewers were fairly united in hating it. Constructing a random type was deemed too unpredictable and not complying with the spirit of the basic guarantee. The default constructor of the chosen type, even if nonthrowing, may still have undesirable side effects. Or, if not that, a value of that type may have special significance for the surrounding code. Therefore, some argued, the `variant` should either remain with its old value, or transition into the new one, without synthesizing other states.

At the other side of the spectrum, there were those who considered double storage unacceptable. But they considered it unacceptable in principle, regardless of the frequency with which it was used.

As a result, providing the strong exception safety guarantee on assignment and `emplace` was declared an acceptance condition.

In retrospect, this was the right decision. The reason the strong guarantee is generally not provided is because it doesn’t compose. When `X` and `Y` provide the basic guarantee on assignment, so does `struct { X x; Y y; };`. Similarly, when `X` and `Y` have nonthrowing assignments, so does the `struct`. But this doesn’t hold for the strong guarantee.

The usual practice is to provide the basic guarantee on assignment and let the user synthesize a "strong" assignment out of either a nonthrowing `swap` or a nonthrowing move assignment. That is, given `x1` and `x2` of type `X`, instead of the "basic" `x1 = x2;`, use either `X(x2).swap(x1);` or `x1 = X(x2);`.

Nearly all types provide a nonthrowing `swap` or a nonthrowing move assignment, so this works well. Nearly all, except `variant`, which in the general case has neither a nonthrowing `swap` nor a nonthrowing move assignment. If `variant` does not provide the strong guarantee itself, it’s impossible for the user to synthesize it.

So it should, and so it does.

### Differences with std::variant

The main differences between this implementation and `std::variant` are:

- No valueless-by-exception state: `valueless_by_exception()` always returns `false`.

- Strong exception safety guarantee on assignment and `emplace`.

- `emplace` first constructs the new value and then destroys the old one; in the single storage case, this translates to constructing a temporary and then moving it into place.

- A converting constructor from, e.g. `variant<int, float>` to `variant<float, double, int>` is provided as an extension.

- The reverse operation, going from `variant<float, double, int>` to `variant<int, float>` is provided as the member function `subset<U…​>`. (This operation can throw if the current state of the variant cannot be represented.)

- `unsafe_get`, an unchecked alternative to `get` and `get_if`, is provided as an extension.

- `visit_by_index`, a visitation function that takes a single variant and a number of function objects, one per alternative, is provided as an extension.

- The C++20 additions and changes to `std::variant` have not yet been implemented.

### Differences with Boost.Variant

This library is API compatible with `std::variant`. As such, its interface is different from Boost.Variant’s. For example, visitation is performed via `visit` instead of `apply_visitor`.

Recursive variants are not supported.

Double storage is used instead of temporary heap backup. This `variant` is always "stack-based", it never allocates, and never throws `bad_alloc` on its own.

## Implementation

### Dependencies

This implementation only depends on Boost.Config, Boost.Assert, and Boost.Mp11.

### Supported Compilers

- GCC 4.8 or later with `-std=c++11` or above

- Clang 3.9 or later with `-std=c++11` or above

- Visual Studio 2015, 2017, 2019

Tested on Github Actions and Appveyor.

## Reference

### <boost/variant2/variant.hpp>

#### Synopsis

    namespace boost {
    namespace variant2 {

    // in_place_type

    template<class T> struct in_place_type_t {};
    template<class T> constexpr in_place_type_t<T> in_place_type{};

    // in_place_index

    template<std::size_t I> struct in_place_index_t {};
    template<std::size_t I> constexpr in_place_index_t<I> in_place_index{};

    // variant

    template<class... T> class variant;

    // variant_size

    template<class T> struct variant_size {};

    template<class T> struct variant_size<T const>: variant_size<T> {};
    template<class T> struct variant_size<T volatile>: variant_size<T> {};
    template<class T> struct variant_size<T const volatile>: variant_size<T> {};

    template<class T> struct variant_size<T&>: variant_size<T> {}; // extension
    template<class T> struct variant_size<T&&>: variant_size<T> {}; // extension

    template<class T>
      inline constexpr size_t variant_size_v = variant_size<T>::value;

    template<class... T>
      struct variant_size<variant<T...>>:
        std::integral_constant<std::size_t, sizeof...(T)> {};

    // variant_alternative

    template<size_t I, class T> struct variant_alternative {};

    template<size_t I, class T> struct variant_alternative<I, T const>;
    template<size_t I, class T> struct variant_alternative<I, T volatile>;
    template<size_t I, class T> struct variant_alternative<I, T const volatile>;

    template<size_t I, class T> struct variant_alternative<I, T&>; // extension
    template<size_t I, class T> struct variant_alternative<I, T&&>; // extension

    template<size_t I, class T>
      using variant_alternative_t = typename variant_alternative<I, T>::type;

    template<size_t I, class... T>
      struct variant_alternative<I, variant<T...>>;

    // variant_npos

    constexpr std::size_t variant_npos = -1;

    // holds_alternative

    template<class U, class... T>
      constexpr bool holds_alternative(const variant<T...>& v) noexcept;

    // get

    template<size_t I, class... T>
      constexpr variant_alternative_t<I, variant<T...>>&
        get(variant<T...>& v);
    template<size_t I, class... T>
      constexpr variant_alternative_t<I, variant<T...>>&&
        get(variant<T...>&& v);
    template<size_t I, class... T>
      constexpr const variant_alternative_t<I, variant<T...>>&
        get(const variant<T...>& v);
    template<size_t I, class... T>
      constexpr const variant_alternative_t<I, variant<T...>>&&
        get(const variant<T...>&& v);

    template<class U, class... T>
      constexpr U& get(variant<T...>& v);
    template<class U, class... T>
      constexpr U&& get(variant<T...>&& v);
    template<class U, class... T>
      constexpr const U& get(const variant<T...>& v);
    template<class U, class... T>
      constexpr const U&& get(const variant<T...>&& v);

    // get_if

    template<size_t I, class... T>
      constexpr add_pointer_t<variant_alternative_t<I, variant<T...>>>
        get_if(variant<T...>* v) noexcept;
    template<size_t I, class... T>
      constexpr add_pointer_t<const variant_alternative_t<I, variant<T...>>>
        get_if(const variant<T...>* v) noexcept;

    template<class U, class... T>
      constexpr add_pointer_t<U>
        get_if(variant<T...>* v) noexcept;
    template<class U, class... T>
      constexpr add_pointer_t<const U>
        get_if(const variant<T...>* v) noexcept;

    // unsafe_get (extension)

    template<size_t I, class... T>
      constexpr variant_alternative_t<I, variant<T...>>&
        unsafe_get(variant<T...>& v);
    template<size_t I, class... T>
      constexpr variant_alternative_t<I, variant<T...>>&&
        unsafe_get(variant<T...>&& v);
    template<size_t I, class... T>
      constexpr const variant_alternative_t<I, variant<T...>>&
        unsafe_get(const variant<T...>& v);
    template<size_t I, class... T>
      constexpr const variant_alternative_t<I, variant<T...>>&&
        unsafe_get(const variant<T...>&& v);

    // relational operators

    template<class... T>
      constexpr bool operator==(const variant<T...>& v, const variant<T...>& w);
    template<class... T>
      constexpr bool operator!=(const variant<T...>& v, const variant<T...>& w);
    template<class... T>
      constexpr bool operator<(const variant<T...>& v, const variant<T...>& w);
    template<class... T>
      constexpr bool operator>(const variant<T...>& v, const variant<T...>& w);
    template<class... T>
      constexpr bool operator<=(const variant<T...>& v, const variant<T...>& w);
    template<class... T>
      constexpr bool operator>=(const variant<T...>& v, const variant<T...>& w);

    // stream insertion (extension)

    template<class Ch, class Tr, class... T>
      std::basic_ostream<Ch, Tr>&
        operator<<( std::basic_ostream<Ch, Tr>& os, variant<T...> const& v );

    // swap

    template<class... T>
      void swap(variant<T...>& v, variant<T...>& w) noexcept( /*see below*/ );

    // visit

    template<class R = /*unspecified*/, class F, class... V>
      constexpr /*see below*/ visit(F&& f, V&&... v);

    // visit_by_index (extension)

    template<class R = /*unspecified*/, class V, class... F>
      constexpr /*see below*/ visit_by_index(V&& v, F&&.. f);

    // monostate

    struct monostate {};

    constexpr bool operator==(monostate, monostate) noexcept { return true; }
    constexpr bool operator!=(monostate, monostate) noexcept { return false; }
    constexpr bool operator<(monostate, monostate) noexcept { return false; }
    constexpr bool operator>(monostate, monostate) noexcept { return false; }
    constexpr bool operator<=(monostate, monostate) noexcept { return true; }
    constexpr bool operator>=(monostate, monostate) noexcept { return true; }

    // bad_variant_access

    class bad_variant_access;

    } // namespace variant2
    } // namespace boost

#### variant

    namespace boost {
    namespace variant2 {

    template<class... T> class variant
    {
    public:

      // constructors

      constexpr variant() noexcept( /*see below*/ );

      constexpr variant( variant const & r ) noexcept( /*see below*/ );
      constexpr variant( variant&& r ) noexcept( /*see below*/ );

      template<class U>
        constexpr variant( U&& u ) noexcept( /*see below*/ );

      template<class U, class... A>
        constexpr explicit variant( in_place_type_t<U>, A&&... a );
      template<class U, class V, class... A>
        constexpr explicit variant( in_place_type_t<U>,
          std::initializer_list<V> il, A&&... a );

      template<size_t I, class... A>
        constexpr explicit variant( in_place_index_t<I>, A&&... a );
      template<size_t I, class V, class... A>
        constexpr explicit variant( in_place_index_t<I>,
          std::initializer_list<V> il, A&&... a );

      // destructor

      ~variant();

      // assignment

      constexpr variant& operator=( variant const & r ) noexcept( /*see below*/ );
      constexpr variant& operator=( variant&& r ) noexcept( /*see below*/ );

      template<class U> constexpr variant& operator=( U&& u ) noexcept( /*see below*/ );

      // modifiers

      template<class U, class... A>
        constexpr U& emplace( A&&... a );
      template<class U, class V, class... A>
        constexpr U& emplace( std::initializer_list<V> il, A&&... a );

      template<size_t I, class... A>
        constexpr variant_alternative_t<I, variant<T...>>&
          emplace( A&&... a );
      template<size_t I, class V, class... A>
        constexpr variant_alternative_t<I, variant<T...>>&
          emplace( std::initializer_list<V> il, A&&... a );

      // value status

      constexpr bool valueless_by_exception() const noexcept;
      constexpr size_t index() const noexcept;

      // swap

      void swap( variant& r ) noexcept( /*see below*/ );

      // converting constructors (extension)

      template<class... U> variant( variant<U...> const& r )
        noexcept( /*see below*/ );

      template<class... U> variant( variant<U...>&& r )
        noexcept( /*see below*/ );

      // subset (extension)

      template<class... U> constexpr variant<U...> subset() & ;
      template<class... U> constexpr variant<U...> subset() && ;
      template<class... U> constexpr variant<U...> subset() const& ;
      template<class... U> constexpr variant<U...> subset() const&& ;
    };

    } // namespace variant2
    } // namespace boost

In the descriptions that follow, let `i` be in the range `[0, sizeof…​(T))`, and `Ti` be the `i`-th type in `T…​`.

##### Constructors

    constexpr variant() noexcept( std::is_nothrow_default_constructible_v<T0> );

- Effects:

    Constructs a `variant` holding a value-initialized value of type `T0`.

  Ensures:

    `index() == 0`.

  Throws:

    Any exception thrown by the value-initialization of `T0`.

  Remarks:

    This function does not participate in overload resolution unless `std::is_default_constructible_v<T0>` is `true`.

    constexpr variant( variant const & w )
      noexcept( mp_all<std::is_nothrow_copy_constructible<T>...>::value );

- Effects:

    Initializes the variant to hold the same alternative and value as `w`.

  Throws:

    Any exception thrown by the initialization of the contained value.

  Remarks:

    This function does not participate in overload resolution unless `std::is_copy_constructible_v<Ti>` is `true` for all `i`.

    constexpr variant( variant&& w )
      noexcept( mp_all<std::is_nothrow_move_constructible<T>...>::value );

- Effects:

    Initializes the variant to hold the same alternative and value as `w`.

  Throws:

    Any exception thrown by the move-initialization of the contained value.

  Remarks:

    This function does not participate in overload resolution unless `std::is_move_constructible_v<Ti>` is `true` for all `i`.

    template<class U> constexpr variant( U&& u ) noexcept(/*see below*/);

- Let `Tj` be a type that is determined as follows: build an imaginary function `FUN(Ti)` for each alternative type `Ti`. The overload `FUN(Tj)` selected by overload resolution for the expression `FUN(std::forward<U>(u))` defines the alternative `Tj` which is the type of the contained value after construction.

  Effects:

    Initializes `*this` to hold the alternative type `Tj` and initializes the contained value from `std::forward<U>(u)`.

  Ensures:

    `holds_alternative<Tj>(*this)`.

  Throws:

    Any exception thrown by the initialization of the contained value.

  Remarks:

    The expression inside `noexcept` is equivalent to `std::is_nothrow_constructible_v<Tj, U>`. This function does not participate in overload resolution unless

    - `sizeof…​(T)` is nonzero,

    - `std::is_same_v<std::remove_cvref_t<U>, variant>` is `false`,

    - `std::remove_cvref_t<U>` is neither a specialization of `in_place_type_t` nor a specialization of `in_place_index_t`,

    - `std::is_constructible_v<Tj, U>` is `true`, and

    - the expression `FUN(std::forward<U>(u))` is well-formed.

    template<class U, class... A>
      constexpr explicit variant( in_place_type_t<U>, A&&... a );

- Effects:

    Initializes the contained value of type `U` with the arguments `std::forward<A>(a)…​`.

  Ensures:

    `holds_alternative<U>(*this)`.

  Throws:

    Any exception thrown by the initialization of the contained value.

  Remarks:

    This function does not participate in overload resolution unless there is exactly one occurrence of `U` in `T…​` and `std::is_constructible_v<U, A…​>` is true.

    template<class U, class V, class... A>
      constexpr explicit variant( in_place_type_t<U>, std::initializer_list<V> il,
        A&&... a );

- Effects:

    Initializes the contained value of type `U` with the arguments `il`, `std::forward<A>(a)…​`.

  Ensures:

    `holds_alternative<U>(*this)`.

  Throws:

    Any exception thrown by the initialization of the contained value.

  Remarks:

    This function does not participate in overload resolution unless there is exactly one occurrence of `U` in `T…​` and `std::is_constructible_v<U, initializer_list<V>&, A…​>` is `true`.

    template<size_t I, class... A>
      constexpr explicit variant( in_place_index_t<I>, A&&... a );

- Effects:

    Initializes the contained value of type `TI` with the arguments `std::forward<A>(a)…​`.

  Ensures:

    `index() == I`.

  Throws:

    Any exception thrown by the initialization of the contained value.

  Remarks:

    This function does not participate in overload resolution unless `I < sizeof…​(T)` and `std::is_constructible_v<TI, A…​>` is `true`.

    template<size_t I, class V, class... A>
      constexpr explicit variant( in_place_index_t<I>, std::initializer_list<V> il,
        A&&... a );

- Effects:

    Initializes the contained value of type `TI` with the arguments `il`, `std::forward<A>(a)…​`.

  Ensures:

    `index() == I`.

  Throws:

    Any exception thrown by the initialization of the contained value.

  Remarks:

    This function does not participate in overload resolution unless `I < sizeof…​(T)` and `std::is_constructible_v<TI, initializer_list<V>&, A…​>` is `true`.

##### Destructor

    ~variant();

- Effects:

    Destroys the currently contained value.

##### Assignment

    constexpr variant& operator=( const variant& r )
      noexcept( mp_all<std::is_nothrow_copy_constructible<T>...>::value );

- Let `j` be `r.index()`.

  Effects:

    `emplace<j>(get<j>(r))`.

  Returns:

    `*this`.

  Ensures:

    `index() == r.index()`.

  Remarks:

    This operator does not participate in overload resolution unless `std::is_copy_constructible_v<Ti> && std::is_copy_assignable_v<Ti>` is `true` for all `i`.

    constexpr variant& operator=( variant&& r )
      noexcept( mp_all<std::is_nothrow_move_constructible<T>...>::value );

- Let `j` be `r.index()`.

  Effects:

    `emplace<j>(get<j>(std::move(r)))`.

  Returns:

    `*this`.

  Ensures:

    `index() == r.index()`.

  Remarks:

    This operator does not participate in overload resolution unless `std::is_move_constructible_v<Ti> && std::is_move_assignable_v<Ti>` is `true` for all `i`.

    template<class U> constexpr variant& operator=( U&& u )
      noexcept( /*see below*/ );

- Let `Tj` be a type that is determined as follows: build an imaginary function `FUN(Ti)` for each alternative type `Ti`. The overload `FUN(Tj)` selected by overload resolution for the expression `FUN(std::forward<U>(u))` defines the alternative `Tj` which is the type of the contained value after construction.

  Effects:

    `emplace<j>(std::forward<U>(u))`.

  Returns:

    `*this`.

  Ensures:

    `index() == j`.

  Remarks:

    The expression inside `noexcept` is `std::is_nothrow_constructible_v<Tj, U&&>`. This operator does not participate in overload resolution unless

    - `std::is_same_v<std::remove_cvref_t<T>, variant>` is `false`,

    - `std::is_constructible_v<Tj, U&&> && std::is_assignable_v<Tj&, U&&>` is `true`, and

    - the expression `FUN(std::forward<U>(u))` (with `FUN` being the above-mentioned set of imaginary functions) is well-formed.

##### Modifiers

    template<class U, class... A>
      constexpr U& emplace( A&&... a );

- Let `I` be the zero-based index of `U` in `T…​`.

  Effects:

    Equivalent to: `return emplace<I>(std::forward<A>(a)…​);`

  Remarks:

    This function shall not participate in overload resolution unless `std::is_constructible_v<U, A&&…​>` is `true` and `U` occurs exactly once in `T…​`.

    template<class U, class V, class... A>
      constexpr U& emplace( std::initializer_list<V> il, A&&... a );

- Let `I` be the zero-based index of `U` in `T…​`.

  Effects:

    Equivalent to: `return emplace<I>(il, std::forward<A>(a)…​);`

  Remarks:

    This function shall not participate in overload resolution unless `std::is_constructible_v<U, std::initializer_list<V>&, A&&…​>` is `true` and `U` occurs exactly once in `T…​`.

    template<size_t I, class... A>
      constexpr variant_alternative_t<I, variant<T...>>&
        emplace( A&&... a );

- Requires:

    `I < sizeof…​(T)`.

  Effects:

    Initializes a new contained value as if using the expression `Ti(std::forward<A>(a)…​)`, then destroys the currently contained value.

  Ensures:

    `index() == I`.

  Returns:

    A reference to the new contained value.

  Throws:

    Nothing unless the initialization of the new contained value throws.

  Exception Safety:

    Strong. On exception, the contained value is unchanged.

  Remarks:

    This function shall not participate in overload resolution unless `std::is_constructible_v<Ti, A&&…​>` is `true`.

    template<size_t I, class V, class... A>
      constexpr variant_alternative_t<I, variant<T...>>&
        emplace( std::initializer_list<V> il, A&&... a );

- Requires:

    `I < sizeof…​(T)`.

  Effects:

    Initializes a new contained value as if using the expression `Ti(il, std::forward<A>(a)…​)`, then destroys the currently contained value.

  Ensures:

    `index() == I`.

  Returns:

    A reference to the new contained value.

  Throws:

    Nothing unless the initialization of the new contained value throws.

  Exception Safety:

    Strong. On exception, the contained value is unchanged.

  Remarks:

    This function shall not participate in overload resolution unless `std::is_constructible_v<Ti, std::initializer_list<V>&, A&&…​>` is `true`.

##### Value Status

    constexpr bool valueless_by_exception() const noexcept;

- Returns:

    `false`.

  Note | This function is provided purely for compatibility with `std::variant`.

    constexpr size_t index() const noexcept;

- Returns:

    The zero-based index of the active alternative.

##### Swap

    void swap( variant& r ) noexcept( mp_all<std::is_nothrow_move_constructible<T>...,
      is_nothrow_swappable<T>...>::value );

- Effects:

    - If `index() == r.index()`, calls `swap(get<I>(*this), get<I>(r))`, where `I` is `index()`.

    - Otherwise, as if `variant tmp(std::move(*this)); *this = std::move(r); r = std::move(tmp);`

##### Converting Constructors (extension)

    template<class... U> variant( variant<U...> const& r )
      noexcept( mp_all<std::is_nothrow_copy_constructible<U>...>::value );

- Effects:

    Initializes the contained value from the contained value of `r`.

  Throws:

    Any exception thrown by the initialization of the contained value.

  Remarks:

    This function does not participate in overload resolution unless all types in `U…​` are in `T…​` and `std::is_copy_constructible_v<Ui>::value` is `true` for all `Ui`.

    template<class... U> variant( variant<U...>&& r )
      noexcept( mp_all<std::is_nothrow_move_constructible<U>...>::value );

- Effects:

    Initializes the contained value from the contained value of `std::move(r)`.

  Throws:

    Any exception thrown by the initialization of the contained value.

  Remarks:

    This function does not participate in overload resolution unless all types in `U…​` are in `T…​` and `std::is_move_constructible_v<Ui>::value` is `true` for all `Ui`.

##### Subset (extension)

    template<class... U> constexpr variant<U...> subset() & ;

    template<class... U> constexpr variant<U...> subset() const& ;

- Returns:

    A `variant<U…​>` whose contained value is copy-initialized from the contained value of `*this` and has the same type.

  Throws:

    - If the active alternative of `*this` is not among the types in `U…​`, `bad_variant_access`.

    - Otherwise, any exception thrown by the initialization of the contained value.

  Remarks:

    This function does not participate in overload resolution unless all types in `U…​` are in `T…​` and `std::is_copy_constructible_v<Ui>::value` is `true` for all `Ui`.

    template<class... U> constexpr variant<U...> subset() && ;

    template<class... U> constexpr variant<U...> subset() const&& ;

- Returns:

    A `variant<U…​>` whose contained value is move-initialized from the contained value of `*this` and has the same type.

  Throws:

    - If the active alternative of `*this` is not among the types in `U…​`, `bad_variant_access`.

    - Otherwise, any exception thrown by the initialization of the contained value.

  Remarks:

    This function does not participate in overload resolution unless all types in `U…​` are in `T…​` and `std::is_move_constructible_v<Ui>::value` is `true` for all `Ui`.

#### variant_alternative

    template<size_t I, class T> struct variant_alternative<I, T const>;

    template<size_t I, class T> struct variant_alternative<I, T volatile>;

    template<size_t I, class T> struct variant_alternative<I, T const volatile>;

    template<size_t I, class T> struct variant_alternative<I, T&>; // extension

    template<size_t I, class T> struct variant_alternative<I, T&&>; // extension

- If `typename variant_alternative<I, T>::type` exists and is `U`,

  - `variant_alternative<I, T const>::type` is `U const`;

  - `variant_alternative<I, T volatile>::type` is `U volatile`;

  - `variant_alternative<I, T const volatile>::type` is `U const volatile`.

  - `variant_alternative<I, T&>::type` is `U&`.

  - `variant_alternative<I, T&&>::type` is `U&&`.

  Otherwise, these structs have no member `type`.

    template<size_t I, class... T>
      struct variant_alternative<I, variant<T...>>;

- When `I < sizeof…​(T)`, the nested type `type` is an alias for the `I`-th (zero-based) type in `T…​`. Otherwise, there is no member `type`.

#### holds_alternative

    template<class U, class... T>
      constexpr bool holds_alternative(const variant<T...>& v) noexcept;

- Requires:

    The type `U` occurs exactly once in `T…​`. Otherwise, the program is ill-formed.

  Returns:

    `true` if `index()` is equal to the zero-based index of `U` in `T…​`.

#### get

    template<size_t I, class... T>
      constexpr variant_alternative_t<I, variant<T...>>&
        get(variant<T...>& v);

    template<size_t I, class... T>
      constexpr variant_alternative_t<I, variant<T...>>&&
        get(variant<T...>&& v);

    template<size_t I, class... T>
      constexpr const variant_alternative_t<I, variant<T...>>&
        get(const variant<T...>& v);

    template<size_t I, class... T>
      constexpr const variant_alternative_t<I, variant<T...>>&&
        get(const variant<T...>&& v);

- Effects:

    If `v.index()` is `I`, returns a reference to the object stored in the variant. Otherwise, throws `bad_variant_access`.

  Remarks:

    These functions do not participate in overload resolution unless `I` < `sizeof…​(T)`.

    template<class U, class... T>
      constexpr U& get(variant<T...>& v);

    template<class U, class... T>
      constexpr U&& get(variant<T...>&& v);

    template<class U, class... T>
      constexpr const U& get(const variant<T...>& v);

    template<class U, class... T>
      constexpr const U&& get(const variant<T...>&& v);

- Requires:

    The type `U` occurs exactly once in `T…​`. Otherwise, the program is ill-formed.

  Effects:

    If `v` holds a value of type `U`, returns a reference to that value. Otherwise, throws `bad_variant_access`.

#### get_if

    template<size_t I, class... T>
      constexpr add_pointer_t<variant_alternative_t<I, variant<T...>>>
        get_if(variant<T...>* v) noexcept;

    template<size_t I, class... T>
      constexpr add_pointer_t<const variant_alternative_t<I, variant<T...>>>
        get_if(const variant<T...>* v) noexcept;

- Effects:

    A pointer to the value stored in the variant, if `v != nullptr && v->index() == I`. Otherwise, `nullptr`.

  Remarks:

    These functions do not participate in overload resolution unless `I` < `sizeof…​(T)`.

    template<class U, class... T>
      constexpr add_pointer_t<U>
        get_if(variant<T...>* v) noexcept;

    template<class U, class... T>
      constexpr add_pointer_t<const U>
        get_if(const variant<T...>* v) noexcept;

- Requires:

    The type `U` occurs exactly once in `T…​`. Otherwise, the program is ill-formed.

  Effects:

    Equivalent to: `return get_if<I>(v);` with `I` being the zero-based index of `U` in `T…​`.

#### unsafe_get (extension)

    template<size_t I, class... T>
      constexpr variant_alternative_t<I, variant<T...>>&
        unsafe_get(variant<T...>& v);

    template<size_t I, class... T>
      constexpr variant_alternative_t<I, variant<T...>>&&
        unsafe_get(variant<T...>&& v);

    template<size_t I, class... T>
      constexpr const variant_alternative_t<I, variant<T...>>&
        unsafe_get(const variant<T...>& v);

    template<size_t I, class... T>
      constexpr const variant_alternative_t<I, variant<T...>>&&
        unsafe_get(const variant<T...>&& v);

- Requires:

    `v.index() == I`.

  Returns:

    a reference to the object stored in the variant.

#### Relational Operators

    template<class... T>
      constexpr bool operator==(const variant<T...>& v, const variant<T...>& w);

- Returns:

    `v.index() == w.index() && get<I>(v) == get<I>(w)`, where `I` is `v.index()`.

    template<class... T>
      constexpr bool operator!=(const variant<T...>& v, const variant<T...>& w);

- Returns:

    `!(v == w)`.

    template<class... T>
      constexpr bool operator<(const variant<T...>& v, const variant<T...>& w);

- Returns:

    `v.index() < w.index() || (v.index() == w.index() && get<I>(v) < get<I>(w))`, where `I` is `v.index()`.

    template<class... T>
      constexpr bool operator>(const variant<T...>& v, const variant<T...>& w);

- Returns:

    `w < v`.

    template<class... T>
      constexpr bool operator<=(const variant<T...>& v, const variant<T...>& w);

- Returns:

    `v.index() < w.index() || (v.index() == w.index() && get<I>(v) <= get<I>(w))`, where `I` is `v.index()`.

    template<class... T>
      constexpr bool operator>=(const variant<T...>& v, const variant<T...>& w);

- Returns:

    `w <= v`.

#### Stream Insertion (extension)

    template<class Ch, class Tr, class... T>
      std::basic_ostream<Ch, Tr>&
        operator<<( std::basic_ostream<Ch, Tr>& os, variant<T...> const& v );

- Requires:

    `sizeof…​(T) != 0`.

  Returns:

    `os << get<I>(v)`, where `I` is `v.index()`.

#### swap

    template<class... T>
      void swap(variant<T...>& v, variant<T...>& w) noexcept( /*see below*/ );

- Effects:

    Equivalent to `v.swap(w)`.

#### visit

    template<class R = /*unspecified*/, class F, class... V>
      constexpr /*see below*/ visit(F&& f, V&&... v);

- Returns:

    `std::forward<F>(f)(get<I>(std::forward<V>(v))…​)`, where `I…​` is `v.index()…​`.

  Remarks:

    If `R` is given explicitly, as in `visit<int>`, the return type is `R`. Otherwise, it’s deduced from `F`. All possible applications of `F` to the variant alternatives must have the same return type for this deduction to succeed.

#### visit_by_index (extension)

    template<class R = /*unspecified*/, class V, class... F>
      constexpr /*see below*/ visit_by_index(V&& v, F&&.. f);

- Requires:

    `variant_size<V>::value == sizeof…​(F)`, or the program is ill-formed.

  Returns:

    `std::forward<Fi>(fi)(get<i>(std::forward<V>(v)))`, where `i` is `v.index()` and `Fi` and `fi` are the `i`-th element of `F…​` and `f…​` accordingly.

  Remarks:

    If `R` is given explicitly, as in `visit_by_index<int>`, the return type is `R`. Otherwise, it’s deduced from `F…​` and `V`. All the applications of `Fi` to the corresponding variant alternatives must have the same return type for this deduction to succeed.

#### bad_variant_access

    class bad_variant_access: public std::exception
    {
    public:

        bad_variant_access() noexcept = default;

        char const * what() const noexcept
        {
            return "bad_variant_access";
        }
    };

### <boost/variant2.hpp>

This convenience header includes `<boost/variant2/variant.hpp>`.

## Copyright and License

This documentation is copyright 2018, 2019 Peter Dimov and is distributed under the Boost Software License, Version 1.0.