Saltar a contenido

Última actualización:2026-10-12

Deducción de argumentos de plantilla de clase CTAD en C++17

Introducción

La metaprogramación de plantillas de C++ siempre ha sido una función bien conocida entre quienes desarrollan en C++: tanto principiantes como desarrolladores avanzados pueden escribir con ella código genérico con parámetros de tipo. Con la deducción de argumentos de plantilla de clase (CTAD) introducida en C++17, el manejo de las plantillas de clase se vuelve más intuitivo y flexible.

Todo el código de esta sección también se actualizará en la comunidad.

La introducción de CTAD en C++17 aporta ventajas como estas:

Por ejemplo: un código tan complejo como este

std::vector<FooBar<int, const char*>> obj{a, b, c}; 

Nos basta con:

 std::vector obj{a, b, c};

Otro ejemplo:

std::tuple<int>

Se puede simplificar a:

std::tuple t1{1};

Así que hoy echemos un vistazo a CTAD.

CTAD proviene de Class template argument deduction (CTAD), la deducción de argumentos de plantilla de clase: basta con darle al compilador una guía de deducción (deduction guide) para poder usar esta característica.

Si no se proporciona, como en el siguiente ejemplo:

#include <iostream>
template <typename T, typename U>
struct MyPair {
  T first{};
  U second{};
};

int main() {
  MyPair<int, int> p1{1, 2};
  MyPair p2{1, 2};
  std::cout << p1.first << ", " << p1.second << std::endl;
  std::cout << p2.first << ", " << p2.second << std::endl;
  return 0;
}

Para p2 obtendremos un error:

no viable constructor or deduction guide for deduction of template arguments of 'MyPair'

¿Y cómo corregirlo?

Basta con añadir el deduction guide, escribiéndolo así:

template <typename T, typename U>
MyPair(T, U) -> MyPair<T, U>;

La deducción de argumentos de plantilla de clase (CTAD) simplifica la instanciación de plantillas de clase al permitir que el compilador deduzca los parámetros de plantilla a partir de los argumentos del constructor. Antes de CTAD, al instanciar había que especificar los parámetros de plantilla de forma explícita. Con CTAD esa especificación explícita deja de ser necesaria, lo que hace el código más legible y fácil de mantener.

template <typename T>
class Add{
    private:
        T first;
        T second;
    public:
        Add() = default;
        Add(T first, T second): first_{first}, second_{second} {}
        T result() const { return first + second; }
};

int main(){
    Add one(1,2);               // T被推导为int
    Add two{1.245, 3.1415};     // T被推导为double
    Add three = {0.24f, 0.34f}; // T被推导为float
}

En el ejemplo anterior, CTAD permite que el tipo T se deduzca a partir de los argumentos del constructor, eliminando la necesidad de especificar el tipo de forma explícita.

Inicialización de miembros no estáticos

Sin embargo, hay un escenario en el que CTAD no se puede usar: la inicialización de miembros no estáticos. Por ejemplo: para usar el MyPair externo dentro de la clase Test hay que escribirlo completo.

template <typename T = int, typename U = int>
struct MyPair {
  T first{};
  U second{};
};

template <typename T, typename U>
MyPair(T, U) -> MyPair<T, U>;

class Test {
  MyPair p4;   // use of class template 'MyPair' requires template arguments; argument
               // deduction not allowed in non-static class member
};

En el ejemplo anterior, definimos una plantilla de clase MyPair y usamos CTAD en ella. Sin embargo, al intentar usar MyPair como miembro no estático en la clase Test, debido al contexto de la inicialización de miembros no estáticos, CTAD no funciona correctamente y provoca un error de compilación. En este caso, debemos especificar explícitamente los parámetros de plantilla de MyPair.

Podemos ver que, en el contexto de la inicialización de miembros no estáticos, CTAD no puede deducir los parámetros de plantilla. Por tanto, cuando una plantilla de clase se usa como miembro no estático, quien desarrolla debe especificar explícitamente todos los parámetros de plantilla. Conviene prestar especial atención a esto en el desarrollo real, para garantizar la corrección y la mantenibilidad del código.

Temas relacionados

Comentarios