Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
std::visit(3)		      C++ Standard Libary		 std::visit(3)

NAME
       std::visit - std::visit

Synopsis
	  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>
       (2) (since C++20)
	  constexpr R visit( Visitor&& vis, Variants&&... vars );

	  Applies the visitor vis (Callable that can be	called with any	combi-
       nation of types
	  from variants) to the	variants vars.

	  These	 overloads  participate	 in  overload resolution only if every
       type in
	  std::remove_reference_t<Variants>... is a (possibly const-qualified)
       specialization
	  of std::variant, or a	(possibly const-qualified) class C  such  that
       there is	exactly
	  one  std::variant specialization that	is a base class	of C and it is
       a public	and
	  unambiguous base class.

	  Effectively returns

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

	  , where every	type in	VariantBases...	 is  the  unique  std::variant
       specialization
	  determined  above, except that const,	&, or && is added to it	if the
       corresponding
	  argument is of a const-qualified  type,  is  an  lvalue,  or	is  an
       rvalue, respectively,
	  and is... is std::forward<VariantBases>(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.
	  If R is a reference type and the implicit conversion from the	result
       of the
	  std::invoke call would bind the returned reference  to  a  temporary
       object, the
	  program is ill-formed.
	  (since C++23)

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	value-
       less_by_exception.
	  Whether any variant is valueless by exception	is determined as if by
	  (std::forward<VariantBases>(vars).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.

Notes
	  Let	n   be	 (1  *	...  *	std::variant_size_v<std::remove_refer-
       ence_t<VariantBases>>),
	  implementations usually generate a table equivalent to an (possibly
	  multidimensional) array of n function	pointers for every specializa-
       tion of
	  std::visit, which is similar to the implementation of	virtual	 func-
       tions.

	  Implementations may also generate a switch statement 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
       vis can be
	  considered equal to that of access to	an  element  in	 an  (possibly
       multidimensional)
	  array	or execution of	a switch statement.

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 constant for the visitor #3
	template<class>	inline constexpr bool always_false_v = false;

	// helper type for the visitor #4
	template<class...  Ts>	struct	overloaded  : Ts... { using Ts::opera-
       tor()...; };
	// explicit deduction guide (not needed	as of C++20)
	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 re-
       turning 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_v<T>, "non-exhaustive visi-
       tor!");
		}, 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 {
		    [](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 "hel-
       lohello"
	10 15 1.500000 "hello"

	 Defect	reports

	  The following	behavior-changing defect reports were applied retroac-
       tively to
	  previously published C++ standards.

	     DR	     Applied	to		   Behavior    as    published
       Correct behavior
	  LWG  3052  C++17	 the  effects  were unspecified	if any type in
       specified
			      Variants is not a	std::variant

See also
	  swap swaps with another variant
	       (public member function)

http://cppreference.com		  2022.07.31			 std::visit(3)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=std::visit&sektion=3&manpath=FreeBSD+Ports+15.0>

home | help