[variant.visit]

# 22 General utilities library [[utilities]](./#utilities)

## 22.6 Variants [[variant]](variant#visit)

### 22.6.7 Visitation [variant.visit]

[ð](#lib:visit)

`template<class Visitor, class... Variants>
  constexpr see below visit(Visitor&& vis, Variants&&... vars);
template<class R, class Visitor, class... Variants>
  constexpr R visit(Visitor&& vis, Variants&&... vars);
`

[1](#1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6802)

Let *as-variant* denote the following exposition-only function templates:template<class... Ts>constexpr auto&& *as-variant*(variant<Ts...>& var) { return var; }template<class... Ts>constexpr auto&& *as-variant*(const variant<Ts...>& var) { return var; }template<class... Ts>constexpr auto&& *as-variant*(variant<Ts...>&& var) { return std::move(var); }template<class... Ts>constexpr auto&& *as-variant*(const variant<Ts...>&& var) { return std::move(var); }

Let n be sizeof...(Variants)[.](#1.sentence-2)

For each 0â¤i<n, letVi denote the type  
decltype(*as-variant*(std​::​forward<Variantsi>(varsi)))[.](#1.sentence-3)

[2](#2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6819)

*Constraints*: Vi is a valid type for all 0â¤i<n[.](#2.sentence-1)

[3](#3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6823)

Let V denote the pack of types Vi[.](#3.sentence-1)

[4](#4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6826)

Let m be a pack of n values of type size_t[.](#4.sentence-1)

Such a pack is valid if  
0â¤mi<variant_size_v<remove_reference_t<Vi>> for all 0â¤i<n[.](#4.sentence-2)

For each valid pack m, let e(m) denote the expression:*INVOKE*(std::forward<Visitor>(vis), *GET*<m>(std::forward<V>(vars))...) // see [[func.require]](func.require "22.10.4 Requirements") for the first form and*INVOKE*<R>(std::forward<Visitor>(vis), *GET*<m>(std::forward<V>(vars))...) // see [[func.require]](func.require "22.10.4 Requirements") for the second form[.](#4.sentence-3)

[5](#5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6841)

*Mandates*: For each valid pack m, e(m) is a valid expression[.](#5.sentence-1)

All such expressions are of the same type and value category[.](#5.sentence-2)

[6](#6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6846)

*Returns*: e(m), where m is the pack for whichmi is *as-variant*(varsi).index() for all 0â¤i<n[.](#6.sentence-1)

The return type is decltype(e(m)) for the first form[.](#6.sentence-2)

[7](#7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6853)

*Throws*: bad_variant_access if(*as-variant*(vars).valueless_by_exception() || ...) is true[.](#7.sentence-1)

[8](#8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6859)

*Complexity*: For n â¤ 1, the invocation of the callable object is
implemented in constant time, i.e., for n=1, it does not depend on
the number of alternative types of V0[.](#8.sentence-1)

For n>1, the invocation of the callable object has
no complexity requirements[.](#8.sentence-2)

[ð](#lib:visit,variant_)

`template<class Self, class Visitor>
  constexpr decltype(auto) visit(this Self&& self, Visitor&& vis);
`

[9](#9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6875)

Let V be*OVERRIDE_REF*(Self&&, *COPY_CONST*(remove_reference_t<Self>, variant)) ([[forward]](forward "22.2.4 Forward/move helpers"))[.](#9.sentence-1)

[10](#10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6879)

*Constraints*: The call to visit does not use
an explicit [*template-argument-list*](temp.names#nt:template-argument-list "13.3 Names of template specializations [temp.names]") that
begins with a type [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")[.](#10.sentence-1)

[11](#11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6885)

*Effects*: Equivalent to: return std​::​visit(std​::​forward<Visitor>(vis), (V)self);

[ð](#lib:visit,variant__)

`template<class R, class Self, class Visitor>
  constexpr R visit(this Self&& self, Visitor&& vis);
`

[12](#12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6897)

Let V be*OVERRIDE_REF*(Self&&, *COPY_CONST*(remove_reference_t<Self>, variant)) ([[forward]](forward "22.2.4 Forward/move helpers"))[.](#12.sentence-1)

[13](#13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6901)

*Effects*: Equivalent to: return std​::​visit<R>(std​::​forward<Visitor>(vis), (V)self);
