std::tuple<Types...>::tuple
| Definido en el encabezado <tuple>
|
||
constexpr tuple();
|
(1) | (desde C++11) (explícito condicionalmente) |
tuple( const Types&... args );
|
(2) | (desde C++11) (constexpr desde C++14) (explícito condicionalmente) |
template< class... UTypes >
tuple( UTypes&&... args );
|
(3) | (desde C++11) (constexpr desde C++14) (explícito condicionalmente) |
template< class... UTypes >
constexpr tuple( tuple<UTypes...>& other );
|
(4) | (desde C++23) (explícito condicionalmente) |
template< class... UTypes >
tuple( const tuple<UTypes...>& other );
|
(5) | (desde C++11) (constexpr desde C++14) (explícito condicionalmente) |
template< class... UTypes >
tuple( tuple<UTypes...>&& other );
|
(6) | (desde C++11) (constexpr desde C++14) (explícito condicionalmente) |
template< class... UTypes >
constexpr tuple( const tuple<UTypes...>&& other );
|
(7) | (desde C++23) (explícito condicionalmente) |
template< class U1, class U2 >
constexpr tuple( std::pair<U1, U2>& p );
|
(8) | (desde C++23) (explícito condicionalmente) |
template< class U1, class U2 >
tuple( const std::pair<U1, U2>& p );
|
(9) | (desde C++11) (constexpr desde C++14) (explícito condicionalmente) |
template< class U1, class U2 >
tuple( std::pair<U1, U2>&& p );
|
(10) | (desde C++11) (constexpr desde C++14) (explícito condicionalmente) |
template< class U1, class U2 >
constexpr tuple( const std::pair<U1, U2>&& p );
|
(11) | (desde C++23) (explícito condicionalmente) |
template< tuple-like UTuple >
constexpr tuple( UTuple&& u );
|
(12) | (desde C++23) (explícito condicionalmente) |
tuple( const tuple& other ) = default;
|
(13) | (desde C++11) |
tuple( tuple&& other ) = default;
|
(14) | (desde C++11) |
| Constructores con extensión de asignador |
||
template< class Alloc >
tuple( std::allocator_arg_t, const Alloc& a );
|
(15) | (desde C++11) (constexpr desde C++20) (explícito condicionalmente) |
template< class Alloc >
tuple( std::allocator_arg_t, const Alloc& a,
const Types&... args );
|
(16) | (desde C++11) (constexpr desde C++20) (explícito condicionalmente) |
template< class Alloc, class... UTypes >
tuple( std::allocator_arg_t, const Alloc& a,
UTypes&&... args );
|
(17) | (desde C++11) (constexpr desde C++20) (explícito condicionalmente) |
template< class Alloc, class... UTypes >
constexpr tuple( std::allocator_arg_t, const Alloc& a,
tuple<UTypes...>& other );
|
(18) | (desde C++23) (explícito condicionalmente) |
template< class Alloc, class... UTypes >
tuple( std::allocator_arg_t, const Alloc& a,
const tuple<UTypes...>& other );
|
(19) | (desde C++11) (constexpr desde C++20) (explícito condicionalmente) |
template< class Alloc, class... UTypes >
tuple( std::allocator_arg_t, const Alloc& a,
tuple<UTypes...>&& other );
|
(20) | (desde C++11) (constexpr desde C++20) (explícito condicionalmente) |
template< class Alloc, class... UTypes >
constexpr tuple( std::allocator_arg_t, const Alloc& a,
const tuple<UTypes...>&& other );
|
(21) | (desde C++23) (explícito condicionalmente) |
template< class Alloc, class U1, class U2 >
constexpr tuple( std::allocator_arg_t, const Alloc& a,
std::pair<U1, U2>& p );
|
(22) | (desde C++23) (explícito condicionalmente) |
template< class Alloc, class U1, class U2 >
tuple( std::allocator_arg_t, const Alloc& a,
const std::pair<U1, U2>& p );
|
(23) | (desde C++11) (constexpr desde C++20) (explícito condicionalmente) |
template< class Alloc, class U1, class U2 >
tuple( std::allocator_arg_t, const Alloc& a,
std::pair<U1, U2>&& p );
|
(24) | (desde C++11) (constexpr desde C++20) (explícito condicionalmente) |
template< class Alloc, class U1, class U2 >
constexpr tuple( std::allocator_arg_t, const Alloc& a,
const std::pair<U1, U2>&& p );
|
(25) | (desde C++23) (explícito condicionalmente) |
template< class Alloc, tuple-like UTuple >
constexpr tuple( std::allocator_arg_t, const Alloc& a, UTuple&& u );
|
(26) | (desde C++23) (explícito condicionalmente) |
template< class Alloc >
tuple( std::allocator_arg_t, const Alloc& a,
const tuple& other );
|
(27) | (desde C++11) (constexpr desde C++20) |
template< class Alloc >
tuple( std::allocator_arg_t, const Alloc& a,
tuple&& other );
|
(28) | (desde C++11) (constexpr desde C++20) |
Construye una nueva tupla.
En las descripciones que siguen, sea
ien el rango[0,sizeof...(Types))en orden,Tieliésimo tipo enTypes, yUieliésimo tipo en un paquete de parámetros de plantilla llamadoUTypes,
donde la indexación comienza en cero.
sizeof...(Types) == 0.
- Esta sobrecarga participa en la resolución de sobrecarga solo si
std::is_default_constructible<Ti>::valueestruepara todoi. - El constructor es
explicitsi y solo siTino es inicializable por lista de copia desde{}para al menos uni.
- Esta sobrecarga participa en la resolución de sobrecarga solo si
sizeof...(Types) >= 1ystd::is_copy_constructible<Ti>::valueestruepara todoi. - Este constructor es
explicitsi y solo sistd::is_convertible<const Ti&, Ti>::valueesfalsepara al menos uni.
std::forward<UTypes>(args).
- Esta sobrecarga participa en la resolución de sobrecarga solo si
sizeof...(Types) == sizeof...(UTypes),sizeof...(Types) >= 1,std::is_constructible<Ti, Ui>::valueestruepara todoi, y- sea
Dstd::decay<U0>::type(hasta C++20)std::remove_cvref_t<U0>(desde C++20),- si
sizeof...(Types) == 1, entoncesDno esstd::tuple, en caso contrario, - si
sizeof...(Types) == 2osizeof...(Types) == 3, entonces oDno es std::allocator_arg_t, oT0es std::allocator_arg_t.
- si
- El constructor es
explicitsi y solo sistd::is_convertible<Ui, Ti>::valueesfalsepara al menos uni.
|
(desde C++23) |
other.
Formalmente, sea FWD(other) std::forward<decltype(other)>(other), para todo i, inicializa el iésimo elemento de la tupla con std::get<i>(FWD(other)).
- Esta sobrecarga participa en la resolución de sobrecarga solo si
sizeof...(Types) == sizeof...(UTypes),std::is_constructible_v<Ti, decltype(std::get<i>(FWD(other)))>estruepara todoi, y- o bien
sizeof...(Types)no es1, o- (cuando
Types...se expande aTyUTypes...se expande aU)std::is_convertible_v<decltype(other), T>,std::is_constructible_v<T, decltype(other)>, ystd::is_same_v<T, U>son todosfalse.
- Estos constructores son
explicitsi y solo sistd::is_convertible_v<decltype(std::get<i>(FWD(other))), Ti>esfalsepara al menos uni.
|
(desde C++23) |
p.
Formalmente, sea FWD(p) std::forward<decltype(p)>(p), inicializa el primer elemento con std::get<0>(FWD(p)) y el segundo elemento con std::get<1>(FWD(p)).
- Esta sobrecarga participa en la resolución de sobrecarga solo si
sizeof...(Types) == 2,std::is_constructible_v<T0, decltype(std::get<0>(FWD(p)))>estrue, ystd::is_constructible_v<T1, decltype(std::get<1>(FWD(p)))>estrue.
- El constructor es
explicitsi y solo sistd::is_convertible_v<decltype(std::get<0>(FWD(p))), T0>ostd::is_convertible_v<decltype(std::get<1>(FWD(p))), T1>esfalse.
|
(desde C++23) |
tuple-like constructor. Construye una tupla con cada elemento construido a partir del elemento correspondiente de u.
Formalmente, para todo i, inicializa el iésimo elemento de la tupla con std::get<i>(std::forward<UTuple>(u)).
- Esta sobrecarga participa en la resolución de sobrecarga solo si
std::same_as<std::remove_cvref_t<UTuple>, std::tuple>esfalse,std::remove_cvref_t<UTuple>no es una especialización de std::ranges::subrange,sizeof...(Types)es igual astd::tuple_size_v<std::remove_cvref_t<UTuple>>,std::is_constructible_v<Ti, decltype(std::get<i>(std::forward<UTuple>(u)))>estruepara todoi, y- o bien
sizeof...(Types)no es1, o- (cuando
Types...se expande aT)std::is_convertible_v<UTuple, T>ystd::is_constructible_v<T, UTuple>son ambosfalse.
- Este constructor se define como eliminado si la inicialización de cualquier elemento que sea una referencia lo vinculara a un objeto temporal.
other.
- Este constructor es constexpr si cada operación que realiza es constexpr. Para la tupla vacía
std::tuple<>, es constexpr. std::is_copy_constructible<Ti>::valuedebe sertruepara todoi, en caso contrario el comportamiento no está definido(hasta C++20)el programa está mal formado(desde C++20).
i, inicializa el iésimo elemento de la tupla con std::forward<Ui>(std::get<i>(other)).
- Este constructor es constexpr si cada operación que realiza es constexpr. Para la tupla vacía
std::tuple<>, es constexpr. std::is_move_constructible<Ti>::valuedebe sertruepara todoi, en caso contrario el comportamiento no está definido(hasta C++20)esta sobrecarga no participa en la resolución de sobrecarga(desde C++20).
a se pasa como un argumento adicional al constructor de cada elemento para el cual std::uses_allocator<Ui, Alloc>::value es true.Parámetros
| args | - | valores utilizados para inicializar cada elemento de la tupla |
| other | - | la tupla de valores utilizados para inicializar cada elemento de la tupla |
| p | - | el par de valores utilizados para inicializar ambos elementos de la 2-tupla |
| u | - |
el
tuple-like
objeto de valores utilizados para inicializar cada elemento de la tupla
|
| a | - | el asignador a utilizar en la construcción uses-allocator |
Notas
Los constructores condicionalmente explícitos hacen posible construir una tupla en contexto de inicialización por copia usando sintaxis de inicialización de lista:
std::tuple<int, int> foo_tuple() { // return {1, -1}; // Error antes de N4387 return std::make_tuple(1, -1); // Siempre funciona }
Tenga en cuenta que si algún elemento de la lista no es convertible implícitamente al elemento correspondiente de la tupla destino, los constructores se vuelven explícitos:
using namespace std::chrono; void launch_rocket_at(std::tuple<hours, minutes, seconds>); launch_rocket_at({hours(1), minutes(2), seconds(3)}); // CORRECTO launch_rocket_at({1, 2, 3}); // Error: int no es convertible implícitamente a duration launch_rocket_at(std::tuple<hours, minutes, seconds>{1, 2, 3}); // CORRECTO
Ejemplo
#include <iomanip> #include <iostream> #include <memory> #include <string> #include <string_view> #include <tuple> #include <type_traits> #include <vector> // función auxiliar para imprimir un vector a un flujo template<class Os, class T> Os& operator<<(Os& os, std::vector<T> const& v) { os << '{'; for (auto i{v.size()}; const T& e : v) os << e << (--i ? "," : ""); return os << '}'; } template<class T> void print_single(T const& v) { if constexpr (std::is_same_v<T, std::decay_t<std::string>>) std::cout << std::quoted(v); else if constexpr (std::is_same_v<std::decay_t<T>, char>) std::cout << "'" << v << "'"; else std::cout << v; } // función auxiliar para imprimir una tupla de cualquier tamaño template<class Tuple, std::size_t N> struct TuplePrinter { static void print(const Tuple& t) { TuplePrinter<Tuple, N - 1>::imprimir(t); std::cout << ", "; print_single(std::get<N - 1>(t)); } }; template<class Tuple> struct TuplePrinter<Tuple, 1> { static void print(const Tuple& t) { print_single(std::get<0>(t)); } }; template<class... Args> void print(std::string_view message, const std::tuple<Args...>& t) { std::cout << message << " ("; TuplePrinter<decltype(t), sizeof...(Args)>::imprimir(t); std::cout << ")\n"; } // fin función auxiliar int main() { std::tuple<int, std::string, double> t1; print("Inicializado con valor, t1:", t1); std::tuple<int, std::string, double> t2{42, "Prueba", -3.14}; print("Inicializado con valores, t2:", t2); std::tuple<char, std::string, int> t3{t2}; print("Convertido implícitamente, t3:", t3); std::tuple<int, double> t4{std::make_pair(42, 3.14)}; print("Construido a partir de un par, t4:", t4); // dado Allocator my_alloc con un constructor de un solo argumento // my_alloc(int); use my_alloc(1) to allocate 5 ints in a vector using my_alloc = std::allocator<int>; std::vector<int, my_alloc> v{5, 1, my_alloc{/* 1 */}}; // usar my_alloc(2) para asignar 5 enteros en un vector en una tupla std::tuple<int, std::vector<int, my_alloc>, double> t5 {std::allocator_arg, my_alloc{/* 2 */}, 42, v, -3.14}; print("Construido con asignador, t5:", t5); }
Salida posible:
Inicializado por valor, t1: (0, "", 0)
Inicializado con valores, t2: (42, "Test", -3.14)
Conversión implícita, t3: ('*', "Test", -3)
Construido desde un par, t4: (42, 3.14)
Construido con asignador, t5: (42, {1,1,1,1,1}, -3.14)
Informes de defectos
Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.
| DR | Aplicado a | Comportamiento publicado | Comportamiento correcto |
|---|---|---|---|
| LWG 2510 | C++11 | el constructor por defecto era implícito | hecho condicionalmente-explícito |
| LWG 3121 | C++11 |
el constructor de tupla de 1 elemento podría verificar recursivamente las restricciones;
allocator_arg_t
argumento generaba ambigüedad
|
restringido adicionalmente
el constructor |
| LWG 3158 | C++11 |
el constructor uses-allocator correspondiente
al constructor por defecto era implícito |
hecho condicionalmente-explícito |
| LWG 3211 | C++11 |
si el constructor por defecto de
tuple<>
era trivial no estaba especificado
|
requerido ser trivial |
| LWG 4045 | C++23 |
tuple-like
constructor podría potencialmente crear referencias colgantes
|
definido como eliminado |
| N4387 | C++11 | algunos constructores eran explícitos, impidiendo comportamientos útiles |
la mayoría de constructores hechos
condicionalmente-explícitos |
Véase también
asigna el contenido de un
tuple
a otro
(función miembro pública) |
|
|
(C++11)
|
crea un objeto
tuple
del tipo definido por los tipos de argumento
(plantilla de función) |
|
(C++11)
|
crea un
tuple
de referencias a lvalue o desempaqueta un tuple en objetos individuales
(plantilla de función) |
|
(C++11)
|
crea un
tuple
de
forwarding references
(plantilla de función) |
construye un nuevo
pair
(función miembro pública de
std::pair<T1,T2>
)
|