c++ - tuplas - Construya la tupla a partir de una lista de inicialización heterogénea en la llamada de función
qué son las tuplas en python (2)
En C ++ 17, podrías escribir:
f(std::tuple{3, 3.5, "Hello World!"}, std::tuple{''a'', std::string("b")});
Antes, puedes usar std::make_tuple
:
f(std::make_tuple(3, 3.5, "Hello World!"), std::make_tuple(''a'', std::string("b")));
pero nada para dejar la línea sin modificar y manteniendo la plantilla de función.
Considera la siguiente función
template <class... T, class... U>
void f(std::tuple<T...> t, std::tuple<U...> u)
{
std::cout << sizeof...(T) << " " << sizeof...(U) << std::endl;
}
int main(int argc, char* argv[])
{
f({3, 3.5, "Hello World!"}, {''a'', std::string("b")}); // Fails
return 0;
}
¿Habría alguna forma en C ++ 17 de modificar la firma de la función para que la línea marcada "Fallos" funcione? (Manteniendo esa línea igual).
Mi conjetura es que la respuesta corta es no .
En términos generales, { args... }
no es una tupla y usted incurre en los mismos problemas de deducción y conversión que enfrentaba en C ++ 14.
Dicho esto, en C ++ 14/17 puede hacer esto para simularlo (mínimo, ejemplo de trabajo):
#include<iostream>
#include<string>
#include<tuple>
#include<utility>
template <class... T, class... U>
void f_(std::tuple<T...> t, std::tuple<U...> u) {
std::cout << sizeof...(T) << " " << sizeof...(U) << std::endl;
}
template<typename... T>
auto f(T... t) {
return [tup{std::make_tuple(t...)}](auto... u) {
f_(std::move(tup), std::make_tuple(u...));
};
}
int main(int argc, char* argv[]) {
f(3, 3.5, "Hello World!")(''a'', std::string("b"));
return 0;
}
Las lambdas genéricas hacen la magia por ti y tienes algo similar a lo que quieres con un nivel adicional de direccionamiento indirecto (que generalmente ayuda a resolver cualquier problema).
En C ++ 17 también puedes hacer esto:
f(std::tuple{3, 3.5, "Hello World!"}, std::tuple{''a'', std::string("b")});
Es decir, los tipos de argumentos se deducen directamente de la llamada al constructor en lugar de especificarlos explícitamente. Con un alias puede incluso ir más lejos y reducir las expresiones en el punto de llamada a algo como esto:
f(T{3, 3.5, "Hello World!"}, T{''a'', std::string("b")});
De todos modos, sacrificas la legibilidad por eso y no vale la pena desde mi punto de vista.