std:: visit
|
Défini dans l'en-tête
<variant>
|
||
|
template
<
class
Visitor,
class
...
Variants
>
constexpr /* voir ci-dessous */ visit ( Visitor && v, Variants && ... values ) ; |
(1) | (depuis C++17) |
|
template
<
class
R,
class
Visitor,
class
...
Variants
>
constexpr R visit ( Visitor && v, Variants && ... values ) ; |
(2) | (depuis C++20) |
|
Modèles d'aide
|
||
|
template
<
class
...
Ts
>
auto && as - variant ( std:: variant < Ts... > & value ) ; |
(3) | ( exposition uniquement* ) |
|
template
<
class
...
Ts
>
auto && as - variant ( const std:: variant < Ts... > & value ) ; |
(4) | ( exposition uniquement* ) |
|
template
<
class
...
Ts
>
auto && as - variant ( std:: variant < Ts... > && value ) ; |
(5) | ( exposition uniquement* ) |
|
template
<
class
...
Ts
>
auto && as - variant ( const std:: variant < Ts... > && value ) ; |
(6) | ( exposition uniquement* ) |
Applique le visiteur v (un Callable pouvant être appelé avec n'importe quelle combinaison de types des Variants) aux Variants values .
Soit
VariantBases
comme
decltype
(
as-variant
(
std::
forward
<
Variants
>
(
values
)
)
...
(un pack de
sizeof...
(
Variants
)
types) :
INVOKE
(
std::
forward
<
Visitor
>
(
v
)
,
std
::
get
<
indices
>
(
std::
forward
<
VariantBases
>
(
values
)
)
...
)
,
as-variant
(
values
)
.
index
(
)
...
.
INVOKE<R>
(
std::
forward
<
Visitor
>
(
v
)
,
std
::
get
<
indices
>
(
std::
forward
<
VariantBases
>
(
values
)
)
...
)
,
as-variant
(
values
)
.
index
(
)
...
.
Ces surcharges participent à la résolution de surcharge seulement si chaque type dans
VariantBases
est un type valide. Si l'expression désignée par
INVOKE
ou
INVOKE<R>
(depuis C++20)
est invalide, ou si les résultats de
INVOKE
ou
INVOKE<R>
(depuis C++20)
ont des types ou des catégories de valeur différents pour différents
indices
, le programme est mal formé.
as-variant
acceptent une valeur dont le type peut être
déduit
pour
std::
variant
<
Ts...
>
(c'est-à-dire soit
std::
variant
<
Ts...
>
soit un type dérivé de
std::
variant
<
Ts...
>
), et retournent la valeur
std::variant
avec la même qualification const et catégorie de valeur.
Table des matières |
Paramètres
| v | - | un Callable qui accepte chaque alternative possible de chaque variant dans Variants |
| values | - | liste de variants à passer au visiteur |
Valeur de retour
Exceptions
Lance
std::bad_variant_access
si
as-variant
(
value_i
)
.
valueless_by_exception
(
)
est
true
pour n'importe quel variant
value_i
dans
values
.
Complexité
Lorsque le nombre de variantes est zéro ou un, l'invocation de l'objet appelable est implémentée en temps constant ; c'est-à-dire qu'elle ne dépend pas du nombre de types pouvant être stockés dans la variant.
Si le nombre de variantes est supérieur à un, l'invocation de l'objet appelable n'a aucune exigence de complexité.
Notes
Soit
n
égal à
(
1
*
...
*
std::
variant_size_v
<
std::
remove_reference_t
<
VariantBases
>>
)
, les implémentations génèrent généralement une table équivalente à un tableau (éventuellement multidimensionnel) de
n
pointeurs de fonctions pour chaque spécialisation de
std::visit
, ce qui est similaire à l'implémentation des
fonctions virtuelles
.
Les implémentations peuvent également générer une
instruction switch
avec
n
branches pour
std::visit
(par exemple, l'implémentation MSVC STL utilise une instruction switch lorsque
n
n'est pas supérieur à 256).
Sur les implémentations typiques, la complexité temporelle de l'invocation de v peut être considérée comme équivalente à celle de l'accès à un élément dans un tableau (éventuellement multidimensionnel) ou à l'exécution d'une instruction switch.
| Macro de test de fonctionnalité | Valeur | Std | Fonctionnalité |
|---|---|---|---|
__cpp_lib_variant
|
202102L
|
(C++23)
(DR17) |
std::visit
pour les classes dérivées de
std::variant
|
Exemple
#include <iomanip> #include <iostream> #include <string> #include <type_traits> #include <variant> #include <vector> // la variante à visiter using value_t = std::variant<int, long, double, std::string>; // type d'assistant pour le visiteur #4 template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; }; // guide de déduction explicite (non nécessaire à partir de C++20) template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>; int main() { std::vector<value_t> vec = {10, 15l, 1.5, "bonjour"}; for (auto& v: vec) { // 1. visiteur void, appelé uniquement pour les effets secondaires (ici, pour les E/S) std::visit([](auto&& arg){ std::cout << arg; }, v); // 2. visiteur retournant une valeur, démontre l'idiome de retourner une autre variante value_t w = std::visit([](auto&& arg) -> value_t { return arg + arg; }, v); // 3. visiteur de correspondance de type : une lambda qui traite chaque type différemment std::cout << ". Après doublement, la variante contient "; std::visit([](auto&& arg) { using T = std::decay_t<decltype(arg)>; if constexpr (std::is_same_v<T, int>) std::cout << "int avec valeur " << arg << '\n'; else if constexpr (std::is_same_v<T, long>) std::cout << "long avec valeur " << arg << '\n'; else if constexpr (std::is_same_v<T, double>) std::cout << "double avec valeur " << arg << '\n'; else if constexpr (std::is_same_v<T, std::string>) std::cout << "std::string avec la valeur " << std::quoted(arg) << '\n'; else static_assert(false, "visiteur non exhaustif !"); }, w); } for (auto& v: vec) { // 4. un autre visiteur de correspondance de types : une classe avec 3 operator() surchargés // Note: Le template `(auto arg)` operator() se liera à `int` et `long` // dans ce cas, mais en son absence l'opérateur `(double arg)` operator() // *va également* se lier à `int` et `long` car les deux sont implicitement // convertible en double. Lors de l'utilisation de cette forme, il faut prendre soin // que les conversions implicites sont gérées correctement. 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); } }
Sortie :
10. Après doublement, variant contient int avec valeur 20 15. Après doublement, variant contient long avec valeur 30 1.5. Après doublement, variant contient double avec valeur 3 hello. Après doublement, variant contient std::string avec valeur "hellohello" 10 15 1.500000 "hello"
Rapports de défauts
Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.
| DR | Appliqué à | Comportement publié | Comportement correct |
|---|---|---|---|
| LWG 2970 | C++17 |
le type de retour de la surcharge
(1)
ne préservait pas la
catégorie de valeur du résultat de l'opération
INVOKE
|
préserve |
|
LWG 3052
( P2162R2 ) |
C++17 |
les effets n'étaient pas spécifiés si un type
dans
Variants
n'est pas un
std::variant
|
spécifié |
Voir aussi
|
(C++26)
|
appelle le foncteur fourni avec l'argument contenu par le
variant
(fonction membre publique) |
échange avec un autre
variant
(fonction membre publique) |