Espacios de nombres
Variantes

std::variant<Types...>::variant

De cppreference.com
 
 
Biblioteca de servicios
Apoyo del lenguaje
Apoyo de tipos (tipos básicos, RTTI)
Macros de prueba de característica de la biblioteca (C++20)
Servicios de programa
Funciones variádicas
Apoyo de corrutinas (C++20)
Apoyo de contratos (C++26)
Comparación de tres vías (C++20)
(C++20)
(C++20)(C++20)(C++20)  
(C++20)(C++20)(C++20)

 
 
constexpr variant() noexcept(/* véase más abajo */);
(1) (desde C++17)
constexpr variant( const variant& other );
(2) (desde C++17)
constexpr variant( variant&& other ) noexcept(/* véase más abajo */);
(3) (desde C++17)
template< class T >
constexpr variant( T&& t ) noexcept(/* véase más abajo */);
(4) (desde C++17)
template< class T, class... Args >
constexpr explicit variant( std::in_place_type_t<T>, Args&&... args );
(5) (desde C++17)
template< class T, class U, class... Args >
constexpr explicit variant( std::in_place_type_t<T>,
                            std::initializer_list<U> il, Args&&... args );
(6) (desde C++17)
template< std::size_t I, class... Args >
constexpr explicit variant( std::in_place_index_t<I>, Args&&... args );
(7) (desde C++17)
template< std::size_t I, class U, class... Args >
constexpr explicit variant( std::in_place_index_t<I>,
                            std::initializer_list<U> il, Args&&... args );
(8) (desde C++17)

Construye un nuevo objeto variante.

1) Constructor por defecto. Construye un variante que mantiene el valor inicializado por valor de la primera alternativa cuyo subíndice (index()) es cero.
  • Este constructor es constexpr si y solo si la inicialización de un valor del tipo de la alternativa T_0 satisfaría los requisitos de una función constexpr.
  • Esta sobrecarga solo participa en la resolución de sobrecargas si std::is_default_constructible_v<T_0> es true.
2) Constructor de copia. Si other no es valueless_by_exception, construye un variante que mantiene la misma alternativa que other y directamente inicializa el valor contenido con std::get<other.index()>(other). De lo contrario, inicializa un variante sin valor debido a una excepción (valueless_by_exception).
  • Este constructor se define como eliminado a menos que std::is_copy_constructible_v<T_i> sea true para toda T_i en Types....
  • Es trivial si std::is_trivially_copy_constructible_v<T_i> es true para toda T_i en Types....
3) Constructor de movimiento. Si other no es valueless_by_exception, construye un variante que mantiene la misma alternativa que other y directamente inicializa el valor contenido con std::get<other.index()>(std::move(other)). De lo contrario, inicializa un variante sin valor debido a una excepción (valueless_by_exception).
  • Esta sobrecarga solo participa en la resolución de sobrecargas si std::is_move_constructible_v<T_i> es true para toda T_i en Types....
  • Es trivial si std::is_trivially_move_constructible_v<T_i> es true para toda T_i en Types....
4) Constructor de conversión. Construye un variante que mantiene la alternativa de tipo T_j que se seleccionaría por la resolución de sobrecarga para la expresión F(std::forward<T>(t)) si hubiera una sobrecarga de la función imaginaria F(T_i) para cada T_i de Types... en ámbito al mismo tiempo, excepto que:
  • Una sobrecarga F(T_i) solamente se considera si la declaración T_i x[] = { std::forward<T>(t) }; es válida para alguna variable inventada x;
Directamente inicializa el valor contenido como si fuera por inicialización directa de no lista a partir de std::forward<T>(t).
  • Esta sobrecarga solo participa en la resolución de sobrecargas si
    • sizeof...(Types) > 0,
    • std::decay_t<U> (hasta C++20)std::remove_cvref_t<U> (desde C++20) no es ni del mismo tipo que variant, ni una especialización de std::in_place_type_t, ni una especialización de std::in_place_index_t,
    • std::is_constructible_v<T_j, T> es true,
    • y la expresión F(std::forward<T>(t)) (con F siendo el conjunto de funciones imaginarias mencionadas anteriormente) está bien formada.
  • Este constructor es un constructor constexpr si el constructor seleccionado de T_j es un constructor constexpr.
std::variant<std::string> v("abc"); // de acuerdo
std::variant<std::string, std::string> w("abc"); // mal formado
std::variant<std::string, const char*> x("abc"); // OK, escoge a const char*
std::variant<std::string, bool> y("abc"); // de acuerdo, escoge a string; bool no es un candidato
std::variant<float, long, double> z = 0; // de acuerdo, mantiene un long
                                         // float y double no son candidatos
5) Construye un variante con la alternativa especificada T e inicializa el valor contenido con los argumentos std::forward<Args>(args)....
  • Si el constructor seleccionado de T_j es un constructor constexpr, este constructor también es un constructor constexpr.
  • Esta sobrecarga solo participa en la resolución de sobrecargas si hay exactamente una ocurrencia de T en Types... y std::is_constructible_v<T, Args...> es true.
6) Construye un variante con la alternativa especificada T e inicializa el valor contenido con los argumentos il, std::forward<Args>(args)....
  • Si el constructor seleccionado de T es un constructor constexpr, este constructor también es un constructor constexpr.
  • Esta sobrecarga solo participa en la resolución de sobrecargas si hay exactamente una ocurrencia de T en Types... y std::is_constructible_v<T, initializer_list<U>&, Args...> es true.
7) Construye un variante con la alternativa T_i especificada por el subíndice I e inicializa el valor contenido con los argumentos std::forward<Args>(args)....
  • Si el constructor seleccionado de T_i es un constructor constexpr, este constructor también es un constructor constexpr.
  • Esta sobrecarga solo participa en la resolución de sobrecargas si I < sizeof...(Types) y std::is_constructible_v<T_i, Args...> son true.
8) Construye un variante con la alternativa T_i especificada por el subíndice I e inicializa el valor contenido con los argumentos il, std::forward<Args>(args)....
  • Si el constructor seleccionado de T_i es un constructor constexpr, este constructor también es un constructor constexpr.
  • Esta sobrecarga solo participa en la resolución de sobrecargas si I < sizeof...(Types) y std::is_constructible_v<T_i, std::initializer_list<U>&, Args...> son true.

Parámetros

other - Otro objecto variante cuyo valor contenido hay que copiar o mover.
t - Valor con el cual inicializar el valor contenido.
args... - Argumentos con los cuales inicializar el valor contenido.
il - Lista de inicializadores con la cual inicializar el valor contenido.

Excepciones

1) Puede lanzar cualquier excepción lanzada por la inicialización de un valor de la primera alternativa.
Especificación noexcept:   (desde C++11)
noexcept(std::is_nothrow_default_constructible_v<T_0>)
2) Puede lanzar cualquier excepción lanzada por la inicialización directa de cualquier T_i en Types....
3) Puede lanzar cualquier excepción lanzada por la construcción por movimiento de cualquier T_i en Types....
Especificación noexcept:   (desde C++11)
noexcept( (std::is_nothrow_move_constructible_v<Types> && ...))
4) Puede lanzar cualquier excepción lanzada por la inicialización de la alternativa seleccionada T_j.
Especificación noexcept:   (desde C++11)
noexcept(std::is_nothrow_constructible_v<T_j, T>)
5-8) Puede lanzar cualquier excepción lanzada por llamar al constructor seleccionado de la alternativa seleccionada.

Ejemplo

#include <cassert>
#include <iostream>
#include <string>
#include <variant>
#include <vector>
 
template <class Os> Os& operator<< (Os& os, const std::vector<int>& v) {
    os << "{ ";
    for (int e: v) { std::cout << e << ' '; }
    return os << "}";
}

int main()
{
    {
        std::variant<int, std::string> var; // inicializa primera alternativa por valor
        assert(std::holds_alternative<int>(var) && var.index() == 0 &&
               std::get<int>(var) == 0);
    }
    {
        std::variant<std::string, int> var{"STR"};
            // inicializa primera alternativa con std::string{"STR"};
        assert(var.index() == 0);
        std::cout << "1) " << std::get<std::string>(var) << '\n';
    }
    {
        std::variant<std::string, int> var{42};
            // inicializa segunda alternativa con int = 42;
        assert(std::holds_alternative<int>(var));
        std::cout << "2) " << std::get<int>(var) << '\n';
    }
    {
        std::variant<std::string, std::vector<int>, float> var{
            std::in_place_type<std::string>, 4, 'A'};
            // inicializa primera alternativa con std::string{4, 'A'};
        assert(var.index() == 0);
        std::cout << "3) " << std::get<std::string>(var) << '\n';
    }
    {
        std::variant<std::string, std::vector<int>, char> var{
            std::in_place_type<std::vector<int>>, {1,2,3,4,5} };
            // inicializa segunda alternativa con std::vector{1,2,3,4,5};
        assert(var.index() == 1);
        std::cout << "4) " << std::get<std::vector<int>>(var) << '\n'; 
    }
    {
        std::variant<std::string, std::vector<int>, bool> var{
            std::in_place_index<0>, "ABCDE", 3};
            // inicializa primera alternativa con std::string{"ABCDE", 3};
        assert(var.index() == 0);
        std::cout << "5) " << std::get<std::string>(var) << '\n';
    }
    {
        std::variant<std::string, std::vector<int>, char> var{
            std::in_place_index<1>, 4, 42};
            // inicializa segunda alternativa con std::vector(4, 42);
        assert(std::holds_alternative<std::vector<int>>(var));
        std::cout << "6) " << std::get<std::vector<int>>(var) << '\n';
    }
}

Salida:

1) STR
2) 42
3) AAAA
4) { 1 2 3 4 5 }
5) ABC
6) { 42 42 42 42 }

Informes de defectos

Los siguientes informes de defectos de cambio de comportamiento se aplicaron de manera retroactiva a los estándares de C++ publicados anteriormente.

ID Aplicado a Comportamiento según lo publicado Comportamiento correcto
LWG 2901 C++17 Se proporcionaron constructores conscientes de asignación
de memoria, pero variant no puede soportar asignadores
de memoria apropiadamente
Se eliminaron los constructores
P0739R0 C++17 La plantilla de constructor de conversión interactúa
pobremente con la deducción de argumentos de plantillas de clase
Se añadió restricción
LWG 3024 C++17 El constructor de copia no participa en la resolución de
sobrecarga si cualquier tipo miembro no es copiable
En su lugar se definió como eliminado
P0602R4 C++17 Constructores de copia/movimiento pueden ser no triviales
incluso si los constructores subyacentes son triviales
Se exigió que la trivialidad se propagase
P0608R3 C++17 Constructor de conversión ciegamente ensambla un conjunto de
sobrecargas, lo que conduce a conversiones no deseadas
No se consideran las conversiones de estrechamiento ni Booleanas
P1957R2 C++17 Constructor de conversión para bool no permitía conversiones
implícitas
La conversión de puntero a bool es estrechante
y el constructor de conversión no tiene una excepción para bool
Morty Proxy This is a proxified and sanitized view of the page, visit original site.