tuple make_tuple example create c++ c++11 stdtuple

make_tuple - tuple c++ example



¿Cuál es la razón para `std:: make_tuple`? (3)

Quiero decir, ¿por qué existe std::make_tuple ? Sé que hay situaciones en las que la función reduce la cantidad de caracteres que tiene que escribir porque puede evitar los parámetros de la plantilla. ¿Pero es la única razón? ¿Qué hace a std::tuple especial que la función exista mientras que otras plantillas de clase no tienen tal función? ¿Es solo porque puede usar std::tuple más a menudo en tales situaciones?

Aquí hay dos ejemplos en los que std::make_tuple reduce la cantidad de caracteres:

// Avoiding template parameters in definition of variable. // Consider that template parameters can be very long sometimes. std::tuple<int, double> t(0, 0.0); // without std::make_tuple auto t = std::make_tuple(0, 0.0); // with std::make_tuple // Avoiding template parameters at construction. f(std::tuple<int, double>(0, 0.0)); // without std::make_tuple f(std::make_tuple(0, 0.0)); // with std::make_tuple

Pero como se escribió anteriormente, no tiene una función como esta para muchas otras plantillas de clase.


Podemos encontrar una razón por la que necesitamos make_tuple y las otras utilidades make_ * en la propuesta N3602: Deducción de parámetros de plantilla para constructores que dice ( énfasis mío ):

Este documento propone extender la deducción de parámetros de plantilla para funciones a los constructores de clases de plantilla. La forma más clara de describir el problema y la solución es con algunos ejemplos.

Supongamos que hemos definido lo siguiente.

vector<int> vi1 = { 0, 1, 1, 2, 3, 5, 8 }; vector<int> vi2; template<class Func> class Foo() { public: Foo(Func f) : func(f) {} void operator()(int i) { os << "Calling with " << i << endl; f(i); } private: Func func; };

Actualmente, si queremos crear una instancia de las clases de plantilla, necesitamos especificar los parámetros de la plantilla o usar un envoltorio "make_ *", aprovechar la deducción de parámetros de la plantilla para funciones , o apostar por completo:

pair<int, double> p(2, 4.5); auto t = make_tuple(4, 3, 2.5); copy_n(vi1, 3, back_inserter(vi2)); // Virtually impossible to pass a lambda to a template class'' constructor for_each(vi.begin(), vi.end(), Foo<???>([&](int i) { ...}));

Tenga en cuenta que la propuesta está siendo rastreada a través del número 60 de EWG .


Porque no puedes usar la deducción de argumentos para los constructores. Debe escribir explícitamente std::tuple<int, double>(i,d); .

Lo hace más conveniente para crear una tupla y pasarla a otra función de una sola vez.

takes_tuple(make_tuple(i,d)) vs takes_tuple(tuple<int,double>(i,d)) .

Un lugar menos para cambiar cuando cambia el tipo de i o d , especialmente si hay posibles conversiones entre los tipos antiguo y nuevo.

Si fuera posible escribir std::tuple(i,d); , make_* sería ( probablemente ) redundante.

(No pregunte por qué aquí. Tal vez por razones similares, la sintaxis A a(); no invoca un constructor predeterminado. Existen algunas peculiaridades de sintaxis de c ++ dolorosas).

NOTA DE ACTUALIZACIÓN: Como lo señala Daniel razón, c ++ 17 se mejorará, de modo que la deducción de los argumentos de la plantilla funcionará para los constructores, y dicha delegación se volverá obsoleta.


Sólo para la plantilla de deducción de argumentos. Sin embargo, aquí hay un ejemplo (creado) donde se requiere para usar un lambda:

class A { public: template<typename F> A(const std::tuple<F> &t) { // e.g. std::get<0>(t)(); } }; class B : public A { public: B(int i) : A(std::make_tuple([&i]{ ++i; })) { // Do something with i } };

std::tuple<decltype([&i]{ ++i; })>([&i]{ ++i; }) no se puede usar porque las dos expresiones lambda tienen diferentes tipos. Una envoltura polimórfica como std::function agrega una sobrecarga de tiempo de ejecución. Una clase nombrada con un operator () definido por el usuario operator () funcionaría (lo que también puede ser un amigo de B , dependiendo del contenido del cuerpo del operador). Eso es lo que usamos en ustedes días anteriores a C ++ 11.