Difference between revisions of "cpp/utility/variant/visit"
m (link to ja) |
(Add a less convoluted, simple example.) |
||
Line 94: | Line 94: | ||
hello. After doubling, variant holds std::string with value "hellohello" | hello. After doubling, variant holds std::string with value "hellohello" | ||
10 15 1.500000 "hello" | 10 15 1.500000 "hello" | ||
+ | }} | ||
+ | |||
+ | {{example | ||
+ | | code= | ||
+ | #include <iostream> | ||
+ | #include <variant> | ||
+ | |||
+ | int main(int, char**) { | ||
+ | std::variant<int, float, double> variant{ 42 }; | ||
+ | |||
+ | auto visitor = [](auto value) { | ||
+ | std::cout << "Variant value : " << value << std::endl; | ||
+ | std::cout << "Variant type : " << typeid(value).name() << std::endl; | ||
+ | }; | ||
+ | |||
+ | std::visit(visitor, variant); | ||
+ | variant = 0.1f; | ||
+ | std::visit(visitor, variant); | ||
+ | variant = -0.1; | ||
+ | std::visit(visitor, variant); | ||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | | output= | ||
+ | Variant value : 42 | ||
+ | Variant type : int | ||
+ | Variant value : 0.1 | ||
+ | Variant type : float | ||
+ | Variant value : -0.1 | ||
+ | Variant type : double | ||
}} | }} | ||
Revision as of 11:02, 13 September 2018
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 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.
Contents |
Parameters
vis | - | a Callable 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.
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 <iomanip> #include <iostream> #include <string> #include <type_traits> #include <variant> #include <vector> template<class T> struct always_false : std::false_type {}; using var_t = std::variant<int, long, double, std::string>; 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) { // 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::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) { 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"
#include <iostream> #include <variant> int main(int, char**) { std::variant<int, float, double> variant{ 42 }; auto visitor = [](auto value) { std::cout << "Variant value : " << value << std::endl; std::cout << "Variant type : " << typeid(value).name() << std::endl; }; std::visit(visitor, variant); variant = 0.1f; std::visit(visitor, variant); variant = -0.1; std::visit(visitor, variant); return 0; }
Output:
Variant value : 42 Variant type : int Variant value : 0.1 Variant type : float Variant value : -0.1 Variant type : double
See also
swaps with another variant (public member function) |