Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/utility/variant/visit"

From cppreference.com
< cpp‎ | utility‎ | variant
(Fix indentation in overloaded_visitor)
(rv back to if/else ladder; a class with a bunch of overloads is not an improvement. When std::overload becomes real, than maybe.)
Line 49: Line 49:
  
 
using var_t = std::variant<int, long, double, std::string>;
 
using var_t = std::variant<int, long, double, std::string>;
 
struct overloaded_visitor {
 
    void operator()(int arg) {
 
      std::cout << "int with value " << arg << `\n`;
 
    }
 
 
    void operator()(long arg) {
 
      std::cout << "long with value " << arg << `\n`;
 
    }
 
 
    void operator()(double arg) {
 
      std::cout << "double with value " << arg << `\n`;
 
    }
 
 
    void operator()(const std::string& arg) {
 
      std::cout << "std::string with value " << arg << `\n`;
 
    }
 
};
 
  
 
int main() {
 
int main() {
Line 78: Line 60:
  
 
         std::cout << ". After doubling, variant holds ";
 
         std::cout << ". After doubling, variant holds ";
         // type-matching visitor: A functor with overloaded operator()
+
         // type-matching visitor: can also be a class with 4 overloaded operator()'s
         std::visit(overloaded_visitor(), w);
+
         std::visit([](auto&& arg) {
 +
            using T = std::remove_cv_t<std::remove_reference_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);
 
     }
 
     }
 
}
 
}

Revision as of 15:57, 8 March 2017

 
 
Utilities library
General utilities
Relational operators (deprecated in C++20)
 
 
Defined in header <variant>
template <class Visitor, class... Variants>
constexpr /*see below*/ visit(Visitor&& vis, Variants&&... vars);
(since C++17)

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()....

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.

Contents

Parameters

vis - a Template:concept that accepts every possible alternative from every variant
vars - list of variants to pass to the visitor

Return value

The value returned by the selected invocation of the visitor, converted to the common type of all possible std::invoke expressions.

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

#include <variant>
#include <iostream>
#include <type_traits>
#include <iomanip>
#include <vector>
 
 
template<class T> struct always_false : std::false_type {};
 
using var_t = std::variant<int, long, double, std::string>;
 
int main() {
    std::vector<var_t> vec = {10, 15l, 1.5, "hello"};
    for(auto v: vec) {
        // void visitor, only called for side-effects
        std::visit([](auto&& arg){std::cout << arg;}, v);
 
        // value-returning visitor. A common idiom is to return another variant
        var_t w = std::visit([](auto&& arg) -> var_t {return arg + arg;}, v);
 
        std::cout << ". After doubling, variant holds ";
        // type-matching visitor: can also be a class with 4 overloaded operator()'s
        std::visit([](auto&& arg) {
            using T = std::remove_cv_t<std::remove_reference_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);
    }
}

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"

See also

swaps with another variant
(public member function) [edit]