El estándar C ++ 17 introduce "guías de deducción de plantillas". Supongo que tienen algo que ver con la deducción del argumento de la nueva plantilla para los constructores introducidos en esta versión del estándar, pero aún no he visto una explicación simple, al estilo de las preguntas frecuentes, de qué son y para qué sirven.
¿Qué son las guías de deducción de plantillas en C ++ 17?
¿Por qué (y cuándo) los necesitamos?
¿Cómo los declaro?
Respuestas:
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>
'sT
será tipo. Sabemos cuál es la respuesta;T
debería sertypename std::iterator_traits<Iterator>::value_type
. Pero, ¿cómo le decimos al compilador sin tener que escribirvector<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á lavector
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 uninitializer_list
utiliza explícitamente elvector
'sT
, 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"}; //thing.t is a `std::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.
fuente
vector v{first, last};
no haré lo correcto :(std::string{32,'*'}[0] == ' '
(para ASCII). Pero todo esto ha sido cierto desde C ++ 11.