From cppreference.com
Defined in header
template<classVisitor,class...Variants>constexpr/* see below */visit(Visitor&&v,Variants&&...values); (1) (since C++17)template<classR,classVisitor,class...Variants>constexprRvisit(Visitor&&v,Variants&&...values); (2) (since C++20)Helper templates
template<class...Ts>auto&&/*as-variant*/(std::variant<Ts...>&value); (3) (exposition only*)template<class...Ts>auto&&/*as-variant*/(conststd::variant<Ts...>&value); (4) (exposition only*)template<class...Ts>auto&&/*as-variant*/(std::variant<Ts...>&&value); (5) (exposition only*)template<class...Ts>auto&&/*as-variant*/(conststd::variant<Ts...>&&value); (6) (exposition only*)Applies the visitor v (a
that can be called with any combination of types from Variants) to the Variants values.
Given VariantBases as decltype(as-variant(std::forward<Variants>(values))... (a pack of sizeof...(Variants) types):
1) Invokes v as if by
(std::forward<Visitor>(v),
std::get<indices>(std::forward<VariantBases>(values))...),
where indices is as-variant(values).index()....
2) Invokes v as if by
(std::forward<Visitor>(v),
std::get<indices>(std::forward<VariantBases>(values))...),
where indices is as-variant(values).index()....
These overloads participate in overload resolution only if every type in VariantBases is a valid type. If the expression denoted by
or
(since C++20) is invalid, or the results of
or
(since C++20) have different types or value categories for different indices, the program is ill-formed.
3-6) The exposition-only as-variant function templates accept a value whose type can be
for std::variant<Ts...> (i.e., either std::variant<Ts...> or a type derived from std::variant<Ts...>), and return the
value with the same const-qualification and value category.
3,4) Returns value.
5,6) Returns std::move(value).
Parameters
v - a
that accepts every possible alternative from every variant in Variantsvalues - list of variants to pass to the visitor Return value
1) The result of the
operation. The return type is the type obtained from applying
to the result.
2) Nothing if R is (possibly cv-qualified) void; otherwise the result of the
operation.
Exceptions
Throws
if as-variant(value_i).valueless_by_exception() is true for any variant value_i in values.
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 the number of types can be stored in the variant.
If the number of variants is larger than one, the invocation of the callable object has no complexity requirements.
Notes
Let n be (1*...*std::variant_size_v<std::remove_reference_t<VariantBases>>), implementations usually generate a table equivalent to an (possibly multidimensional) array of n function pointers for every specialization of std::visit, which is similar to the implementation of
.
Implementations may also generate a
with n branches for std::visit (e.g., the MSVC STL implementation uses a switch statement when n is not greater than 256).
On typical implementations, the time complexity of the invocation of v can be considered equal to that of access to an element in an (possibly multidimensional) array or execution of a switch statement.
macro ValueStdFeature
(C++23)
(DR17)std::visit for classes derived from
Example
Run this code
#include<iomanip>#include<iostream>#include<string>#include<type_traits>#include<variant>#include<vector>// the variant to visitusingvalue_t=std::variant<int,long,double,std::string>;// helper type for the visitor #4template<class...Ts>structoverloaded:Ts...{usingTs::operator()...;};// explicit deduction guide (not needed as of C++20)template<class...Ts>overloaded(Ts...)->overloaded<Ts...>;intmain(){std::vector<value_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 variantvalue_tw=std::visit([](auto&&arg)->value_t{returnarg+arg;},v);// 3. type-matching visitor: a lambda that handles each type differentlystd::cout<<". After doubling, variant holds ";std::visit([](auto&&arg){usingT=std::decay_t<decltype(arg)>;ifconstexpr(std::is_same_v<T,int>)std::cout<<"int with value "<<arg<<'\n';elseifconstexpr(std::is_same_v<T,long>)std::cout<<"long with value "<<arg<<'\n';elseifconstexpr(std::is_same_v<T,double>)std::cout<<"double with value "<<arg<<'\n';elseifconstexpr(std::is_same_v<T,std::string>)std::cout<<"std::string with value "<<std::quoted(arg)<<'\n';elsestatic_assert(false,"non-exhaustive visitor!");},w);}for(auto&v:vec){// 4. another type-matching visitor: a class with 3 overloaded operator()'s// Note: The `(auto arg)` template operator() will bind to `int` and `long`// in this case, but in its absence the `(double arg)` operator()// *will also* bind to `int` and `long` because both are implicitly// convertible to double. When using this form, care has to be taken// that implicit conversions are handled correctly.std::visit(overloaded{[](autoarg){std::cout<<arg<<' ';},[](doublearg){std::cout<<std::fixed<<arg<<' ';},[](conststd::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" Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR Applied to Behavior as published Correct behavior
C++17 the return type of overload (1) did not preserve the
value category of the result of the INVOKE operation preserves
(
) C++17 the effects were unspecified if any type
in Variants is not a
specified See also
(C++26)
calls the provided functor with the argument held by the variant
(public member function)
swaps with another variant
(public member function)