std::variant<Tipos...>::variant
De es.cppreference.net
constexpr variant() noexcept(/* see below */);
|
(1) | (desde C++17) |
constexpr variant( const variant& other );
|
(2) | (desde C++17) |
constexpr variant( variant&& other ) noexcept(/* see below */);
|
(3) | (desde C++17) |
template< class T >
constexpr variant( T&& t ) noexcept(/* see below */);
|
(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 variant.
1) Constructor por defecto. Construye un
variant que contiene el valor inicializado por valor de la primera alternativa (index() es cero).
- Este constructor es
constexprsi y solo si la inicialización por valor del tipo alternativoT_0cumpliría los requisitos de una función constexpr. - Esta sobrecarga participa en la resolución de sobrecarga solo si
std::is_default_constructible_v<T_0>estrue.
2) Constructor de copia. Si
other no está sin valor por excepción, construye un variant que contiene la misma alternativa que other e inicializa directamente el valor contenido con *std::get_if<other.index()>(std::addressof(other)). De lo contrario, inicializa una variante sin valor por excepción.
- Este constructor se define como eliminado a menos que
std::is_copy_constructible_v<T_i>seatruepara todosT_ienTypes.... - Es trivial si
std::is_trivially_copy_constructible_v<T_i>estruepara todosT_ienTypes....
3) Constructor de movimiento. Si
other no está sin valor por excepción, construye un variant que contiene la misma alternativa que other e inicializa directamente el valor contenido con std::move(*std::get_if<other.index()>(std::addressof(other))). De lo contrario, inicializa una variante sin valor por excepción.
- Esta sobrecarga participa en la resolución de sobrecarga solo si
std::is_move_constructible_v<T_i>estruepara todosT_ienTypes.... - Es trivial si
std::is_trivially_move_constructible_v<T_i>estruepara todosT_ienTypes....
4) Constructor de conversión. Construye un
variant que contiene el tipo alternativo T_j que sería seleccionado por resolución de sobrecarga para la expresión F(std::forward<T>(t)) si hubiera una sobrecarga de una función imaginaria F(T_i) para cada T_i en Types..., excepto que las conversiones restrictivas no se consideran.
Formalmente:
- Una sobrecarga
F(T_i)solo se considera si la declaraciónT_i x[] = { std::forward<T>(t) };es válida para alguna variable inventadax.
- Una sobrecarga
Inicializa directamente el valor contenido como si fuera por inicialización directa no de lista desde
std::forward<T>(t).
- Esta sobrecarga participa en la resolución de sobrecarga solo si
sizeof...(Types) > 0,std::decay_t<T>(hasta C++20)std::remove_cvref_t<T>(desde C++20) no es del mismo tipo quevariant, 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>estrue,- y la expresión
F(std::forward<T>(t))(con F siendo el conjunto mencionado de funciones imaginarias) está bien formada.
- Este constructor es un constructor
constexprsi el constructor seleccionado deT_jes un constructor constexpr.
std::variant<std::string> v("abc"); // OK
std::variant<std::string, std::string> w("abc"); // ill-formed
std::variant<std::string, const char*> x("abc"); // OK, chooses const char*
std::variant<std::string, bool> y("abc"); // OK, chooses string; bool is not a candidate
std::variant<float, long, double> z = 0; // OK, holds long
// float and double are not candidates
5) Construye un
variant con la alternativa especificada T e inicializa el valor contenido con los argumentos std::forward<Args>(args)....
- Si el constructor seleccionado de
Tes un constructorconstexpr, este constructor también es un constructorconstexpr. - Esta sobrecarga participa en la resolución de sobrecarga solo si hay exactamente una ocurrencia de
TenTypes...ystd::is_constructible_v<T, Args...>estrue.
6) Construye un
variant con la alternativa especificada T e inicializa el valor contenido con los argumentos il, std::forward<Args>(args)....
- Si el constructor seleccionado de
Tes un constructorconstexpr, este constructor también es un constructorconstexpr. - Esta sobrecarga participa en la resolución de sobrecarga solo si hay exactamente una ocurrencia de
TenTypes...ystd::is_constructible_v<T, initializer_list<U>&, Args...>estrue.
7) Construye un
variant con la alternativa T_i especificada por el índice I e inicializa el valor contenido con los argumentos std::forward<Args>(args)....
- Si el constructor seleccionado de
T_ies un constructorconstexpr, este constructor también es un constructorconstexpr. - Esta sobrecarga participa en la resolución de sobrecarga solo si
I < sizeof...(Types)ystd::is_constructible_v<T_i, Args...>estrue.
8) Construye un
variant con la alternativa T_i especificada por el índice I e inicializa el valor contenido con los argumentos il, std::forward<Args>(args)....
- Si el constructor seleccionado de
T_ies un constructorconstexpr, este constructor también es un constructorconstexpr. - Esta sobrecarga participa en la resolución de sobrecarga solo si
I < sizeof...(Types)ystd::is_constructible_v<T_i, std::initializer_list<U>&, Args...>estrue.
Parámetros
| other | - |
otro objeto variant cuyo valor contenido copiar/mover
|
| t | - | valor para inicializar el valor contenido |
| args... | - | argumentos para inicializar el valor contenido |
| il | - | lista de inicialización para inicializar el valor contenido |
Excepciones
1)
Puede lanzar cualquier excepción lanzada por la inicialización de valor de la primera alternativa.
noexcept
especificación:
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...
.
noexcept
especificación:
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
.
noexcept
especificación:
noexcept
(
std::
is_nothrow_constructible_v
<
T_j, T
>
)
5-8)
Puede lanzar cualquier excepción lanzada al llamar al constructor seleccionado de la alternativa seleccionada.
Notas
MSVC STL inicialmente trató P0608R3 como un cambio en C++20. A partir de VS 2022 17.12, MSVC STL también trata P0608R3 como un informe de defectos contra C++17.
Ejemplo
Ejecutar este código
#include <cassert> #include <iostream> #include <string> #include <variant> #include <vector> using vector_t = std::vector<int>; auto& operator<<(auto& out, const vector_t& v) { out << "{ "; for (int e : v) out << e << ' '; return out << '}'; } int main() { // inicializa por valor la primera alternativa std::variant<int, std::string> var0; assert(std::holds_alternative<int>(var0) and var0.index() == 0 and std::get<int>(var0) == 0); // inicializa la primera alternativa con std::string{"STR"}; std::variant<std::string, int> var1{"STR"}; assert(var1.index() == 0); std::cout << "1) " << std::get<std::string>(var1) << '\n'; // inicializa la segunda alternativa con int == 42; std::variant<std::string, int> var2{42}; assert(std::holds_alternative<int>(var2)); std::cout << "2) " << std::get<int>(var2) << '\n'; // inicializa la primera alternativa con std::string{4, 'A'}; std::variant<std::string, vector_t, float> var3 { std::in_place_type<std::string>, 4, 'A' }; assert(var3.index() == 0); std::cout << "3) " << std::get<std::string>(var3) << '\n'; // inicializa la segunda alternativa con std::vector{1,2,3,4,5}; std::variant<std::string, vector_t, char> var4 { std::in_place_type<vector_t>, {1, 2, 3, 4, 5} }; assert(var4.index() == 1); std::cout << "4) " << std::get<vector_t>(var4) << '\n'; // inicializa la primera alternativa con std::string{"ABCDE", 3}; std::variant<std::string, vector_t, bool> var5 {std::in_place_index<0>, "ABCDE", 3}; assert(var5.index() == 0); std::cout << "5) " << std::get<std::string>(var5) << '\n'; // inicializa la segunda alternativa con std::vector(4, 42); std::variant<std::string, vector_t, char> var6 {std::in_place_index<1>, 4, 42}; assert(std::holds_alternative<vector_t>(var6)); std::cout << "6) " << std::get<vector_t>(var6) << '\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 que modifican el comportamiento se aplicaron retroactivamente a los estándares publicados anteriormente de C++.
| DR | Aplicado a | Comportamiento publicado | Comportamiento correcto |
|---|---|---|---|
| LWG 2901 | C++17 |
constructores conscientes del asignador proporcionados pero
variant
no puede soportar adecuadamente asignadores
|
constructores eliminados |
| P0739R0 | C++17 |
la plantilla del constructor de conversión interactúa
deficientemente con la deducción de argumentos de plantilla de clase |
restricción añadida |
| LWG 3024 | C++17 |
el constructor de copia no participa en la
resolución de sobrecarga si algún tipo miembro no es copiable |
definido como eliminado en su lugar |
| P0602R4 | C++17 |
los constructores de copia/movimiento pueden no ser
triviales incluso si los constructores subyacentes son triviales |
requerido propagar trivialidad |
| P0608R3 | C++17 |
el constructor de conversión ensambla ciegamente
un conjunto de sobrecarga, conduciendo a conversiones no intencionadas |
conversiones de estrechamiento y booleanas no consideradas |
| P1957R2 | C++17 |
el constructor de conversión para
bool
no permitía
conversión implícita |
La conversión de puntero a
bool
es de estrechamiento y
el constructor de conversión no tiene excepción para bool |