Las guías de deducción de plantillas son patrones asociados con una clase de plantilla que le dicen al compilador cómo traducir un conjunto de argumentos de constructor (y sus tipos) en parámetros de plantilla para la clase.
El ejemplo más simple es el de std::vector
y su constructor que toma un par de iteradores.
template<typename Iterator>
void func(Iterator first, Iterator last)
{
vector v(first, last);
}
El compilador necesita averiguar qué vector<T>
's T
será tipo. Sabemos cuál es la respuesta; T
debería ser typename std::iterator_traits<Iterator>::value_type
. Pero, ¿cómo le decimos al compilador sin tener que escribir vector<typename std::iterator_traits<Iterator>::value_type>
?
Utiliza una guía de deducción:
template<typename Iterator> vector(Iterator b, Iterator e) ->
vector<typename std::iterator_traits<Iterator>::value_type>;
Esto le dice al compilador que, cuando llame a un vector
constructor que coincida con ese patrón, deducirá la vector
especialización usando el código a la derecha de ->
.
Necesita guías cuando la deducción del tipo de los argumentos no se basa en el tipo de uno de esos argumentos. Inicializar un vector
desde un initializer_list
utiliza explícitamente el vector
's T
, por lo que no necesita una guía.
El lado izquierdo no necesariamente especifica un constructor real. La forma en que funciona es que, si usa la deducción del constructor de plantilla en un tipo, coincide con los argumentos que pasa contra todas las guías de deducción (los constructores reales de la plantilla principal proporcionan guías implícitas). Si hay una coincidencia, la usa para determinar qué argumentos de plantilla proporcionar al tipo.
Pero una vez que se realiza esa deducción, una vez que el compilador descubre los parámetros de la plantilla para el tipo, la inicialización para el objeto de ese tipo procede como si nada de eso sucediera. Es decir, la guía de deducción seleccionada no tiene que coincidir con el constructor seleccionado.
Esto también significa que puede usar guías con agregados e inicialización agregada:
template<typename T>
struct Thingy
{
T t;
};
Thingy(const char *) -> Thingy<std::string>;
Thingy thing{"A String"};
Por lo tanto, las guías de deducción solo se utilizan para determinar el tipo que se está inicializando. El proceso real de inicialización funciona exactamente como antes, una vez que se ha tomado esa determinación.