valores una tuplas tupla son qué que obtener manejo listas lista las definir datos c++ initialization tuples c++17 aggregate-initialization

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.