# std::visit

From cppreference.com
< cpp‎ | utility‎ | variant

Defined in header `<variant>` |  |
template <class Visitor, class... Variants> constexpr /*see below*/ visit(Visitor&& vis, Variants&&... vars); | (1) | (since C++17)
template <class R, class Visitor, class... Variants> constexpr R visit(Visitor&&, Variants&&...); | (2) | (since C++20)

Applies the visitor `vis` to the variants `vars`

Effectively returns

std::invoke ( std::forward <Visitor>(vis), std::get<is>( std::forward <Variants>(vars))...)

, where `is...` is `vars.index()...`.

1) The return type is deduced from the returned expression as if by decltype. The call is ill-formed if the invocation above is not a valid expression of the same type and value category, for all combinations of alternative types of all variants.
2) The return type is `R`. If `R` is (possibly cv-qualified) void, the result of the `invoke` expression is discarded.

### Parameters

vis | - | a Callable that accepts every possible alternative from every variant
vars | - | list of variants to pass to the visitor

### Return value

1) The value returned by the selected invocation of the visitor.
2) Nothing if `R` is (possibly cv-qualified) void; otherwise the value returned by the selected invocation of the visitor, implicitly converted to `R`.

### Exceptions

Throws std::bad_variant_access if any variant in `vars` is `valueless_by_exception`.

### Complexity

When the number of variants is zero or one, the invocation of the callable object is implemented in constant time, i.e. it does not depend on `sizeof...(Types)`.

If the number of variants is larger than 1, the invocation of the callable object has no complexity requirements.

### Example

Run this code

    #include <iomanip>
    #include <iostream>
    #include <string>
    #include <type_traits>
    #include <variant>
    #include <vector>

    // the variant to visit
    using var_t = std::variant<int, long, double, std::string>;

    // helper type for the visitor #3
    template<class T> struct always_false : std::false_type {};

    // helper type for the visitor #4
    template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
    template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

    int main() {
        std::vector<var_t> vec = {10, 15l, 1.5, "hello"};
        for(auto& v: vec) {

            // 1. void visitor, only called for side-effects (here, for I/O)
            std::visit([](auto&& arg){std::cout << arg;}, v);

            // 2. value-returning visitor, demonstrates the idiom of returning another variant
            var_t w = std::visit([](auto&& arg) -> var_t {return arg + arg;}, v);

            // 3. type-matching visitor: a lambda that handles each type differently
            std::cout << ". After doubling, variant holds ";
            std::visit([](auto&& arg) {
                using T = std::decay_t<decltype(arg)>;
                if constexpr (std::is_same_v<T, int>)
                    std::cout << "int with value " << arg << '\n';
                else if constexpr (std::is_same_v<T, long>)
                    std::cout << "long with value " << arg << '\n';
                else if constexpr (std::is_same_v<T, double>)
                    std::cout << "double with value " << arg << '\n';
                else if constexpr (std::is_same_v<T, std::string>)
                    std::cout << "std::string with value " << std::quoted(arg) << '\n';
                else
                    static_assert(always_false<T>::value, "non-exhaustive visitor!");
            }, w);
        }

        for (auto& v: vec) {
            // 4. another type-matching visitor: a class with 3 overloaded operator()'s
            std::visit(overloaded {
                [](auto arg) { std::cout << arg << ' '; },
                [](double arg) { std::cout << std::fixed << arg << ' '; },
                [](const std::string& arg) { std::cout << std::quoted(arg) << ' '; },
            }, v);
        }
    }

Output:

    10. After doubling, variant holds int with value 20
    15. After doubling, variant holds long with value 30
    1.5. After doubling, variant holds double with value 3
    hello. After doubling, variant holds std::string with value "hellohello"
    10 15 1.500000 "hello"

### See also

swap | swaps with another variant (public member function)

Retrieved from "https://en.cppreference.com/mwiki/index.php?title=cpp/utility/variant/visit&oldid=106987"