std:: visit
|
Definido en el encabezado
<variant>
|
||
|
template
<
class
Visitor,
class
...
Variants
>
constexpr /* ver más abajo */ visit ( Visitor && v, Variants && ... values ) ; |
(1) | (desde C++17) |
|
template
<
class
R,
class
Visitor,
class
...
Variants
>
constexpr R visit ( Visitor && v, Variants && ... values ) ; |
(2) | (desde C++20) |
|
Plantillas auxiliares
|
||
|
template
<
class
...
Ts
>
auto && as - variant ( std:: variant < Ts... > & value ) ; |
(3) | ( solo para exposición* ) |
|
template
<
class
...
Ts
>
auto && as - variant ( const std:: variant < Ts... > & value ) ; |
(4) | ( solo para exposición* ) |
|
template
<
class
...
Ts
>
auto && as - variant ( std:: variant < Ts... > && value ) ; |
(5) | ( solo para exposición* ) |
|
template
<
class
...
Ts
>
auto && as - variant ( const std:: variant < Ts... > && value ) ; |
(6) | ( solo para exposición* ) |
Aplica el visitante v (un Callable que puede ser invocado con cualquier combinación de tipos de Variants) a los Variants values .
Dado
VariantBases
como
decltype
(
as-variant
(
std::
forward
<
Variants
>
(
values
)
)
...
(un paquete de
sizeof...
(
Variants
)
tipos):
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
(
)
...
.
Estas sobrecargas participan en la resolución de sobrecarga solo si cada tipo en
VariantBases
es un tipo válido. Si la expresión denotada por
INVOKE
o
INVOKE<R>
(desde C++20)
es inválida, o los resultados de
INVOKE
o
INVOKE<R>
(desde C++20)
tienen tipos diferentes o categorías de valor para diferentes
indices
, el programa está mal formado.
as-variant
aceptan un valor cuyo tipo puede ser
deducido
para
std::
variant
<
Ts...
>
(es decir, ya sea
std::
variant
<
Ts...
>
o un tipo derivado de
std::
variant
<
Ts...
>
), y devuelven el valor
std::variant
con la misma calificación de const y categoría de valor.
Contenidos |
Parámetros
| v | - | un Callable que acepta cada alternativa posible de cada variante en Variants |
| values | - | lista de variantes para pasar al visitante |
Valor de retorno
R
es (posiblemente calificado con cv)
void
; de lo contrario, el resultado de la operación
INVOKE<R>
.
Excepciones
Lanza
std::bad_variant_access
si
as-variant
(
value_i
)
.
valueless_by_exception
(
)
es
true
para cualquier variant
value_i
en
values
.
Complejidad
Cuando el número de variantes es cero o uno, la invocación del objeto invocable se implementa en tiempo constante; es decir, no depende del número de tipos que pueden almacenarse en el variant.
Si el número de variantes es mayor que uno, la invocación del objeto invocable no tiene requisitos de complejidad.
Notas
Sea
n
igual a
(
1
*
...
*
std::
variant_size_v
<
std::
remove_reference_t
<
VariantBases
>>
)
, las implementaciones generalmente generan una tabla equivalente a un arreglo (posiblemente multidimensional) de
n
punteros a función para cada especialización de
std::visit
, lo cual es similar a la implementación de
funciones virtuales
.
Las implementaciones también pueden generar una
sentencia switch
con
n
ramas para
std::visit
(por ejemplo, la implementación de MSVC STL utiliza una sentencia switch cuando
n
no es mayor que 256).
En implementaciones típicas, la complejidad temporal de la invocación de v puede considerarse igual a la del acceso a un elemento en un arreglo (posiblemente multidimensional) o la ejecución de una sentencia switch.
| Macro de prueba de características | Valor | Estándar | Característica |
|---|---|---|---|
__cpp_lib_variant
|
202102L
|
(C++23)
(DR17) |
std::visit
para clases derivadas de
std::variant
|
Ejemplo
#include <iomanip> #include <iostream> #include <string> #include <type_traits> #include <variant> #include <vector> // la variante a visitar using value_t = std::variant<int, long, double, std::string>; // tipo auxiliar para el visitante #4 template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; }; // guía de deducción explícita (no necesaria a partir de C++20) template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>; int main() { std::vector<value_t> vec = {10, 15l, 1.5, "hola"}; for (auto& v: vec) { // 1. void visitor, solo se llama para efectos secundarios (aquí, para E/S) std::visit([](auto&& arg){ std::cout << arg; }, v); // 2. visitor que retorna un valor, demuestra el modismo de retornar otra variante value_t w = std::visit([](auto&& arg) -> value_t { return arg + arg; }, v); // 3. visitante de coincidencia de tipos: una lambda que maneja cada tipo de manera diferente std::cout << ". Después de duplicar, la variante contiene "; std::visit([](auto&& arg) { using T = std::decay_t<decltype(arg)>; if constexpr (std::is_same_v<T, int>) std::cout << "int con valor " << arg << '\n'; else if constexpr (std::is_same_v<T, long>) std::cout << "long con valor " << arg << '\n'; else if constexpr (std::is_same_v<T, double>) std::cout << "double con valor " << arg << '\n'; else if constexpr (std::is_same_v<T, std::string>) std::cout << "std::string con valor " << std::quoted(arg) << '\n'; else static_assert(false, "¡visitante no exhaustivo!"); }, w); } for (auto& v: vec) { // 4. otro tipo de visitor de coincidencia de tipos: una clase con 3 operator() sobrecargados // Nota: El operador de plantilla `(auto arg)` se vinculará a `int` y `long` // en este caso, pero en su ausencia el operador `(double arg)` operator() // *también* se vinculará a `int` y `long` porque ambos son implícitamente // convertible to double. Al usar esta forma, se debe tener cuidado // que las conversiones implícitas se manejan correctamente. 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); } }
Salida:
10. Después de duplicar, variant contiene int con valor 20 15. Después de duplicar, variant contiene long con valor 30 1.5. Después de duplicar, variant contiene double con valor 3 hello. Después de duplicar, variant contiene std::string con valor "hellohello" 10 15 1.500000 "hello"
Informes de defectos
Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares publicados anteriormente de C++.
| DR | Aplicado a | Comportamiento publicado | Comportamiento correcto |
|---|---|---|---|
| LWG 2970 | C++17 |
el tipo de retorno de la sobrecarga
(1)
no preservaba la
categoría de valor del resultado de la operación
INVOKE
|
preserva |
|
LWG 3052
( P2162R2 ) |
C++17 |
los efectos no estaban especificados si algún tipo
en
Variants
no es un
std::variant
|
especificado |
Véase también
|
(C++26)
|
llama al functor proporcionado con el argumento contenido por el
variant
(función miembro pública) |
intercambia con otro
variant
(función miembro pública) |