Referencias de redireccionamiento: origen del parámetro de referencia.
La premisa completa sobre las referencias hacia adelante (también conocidas como referencias universales) es que esta función:
template<typename t="">
void f(T&&) { }
puede resultar en que el parámetro de la plantilla sea tanto int&
como int
, dependiendo si se llama con int a{}; f(a)
o f(5)
como ejemplo. Pero creo que esto ya es ir demasiado lejos. Porque cuando tengo una función como
template<typename t="">
auto g(T) -> void {}
Siempre resuelve el parámetro de la plantilla como int
, sin importar cómo lo llame. Y eso a pesar de que auto h(int&) -> void {}
sería perfectamente legal.
Entonces, ¿qué reglas están en vigencia que permiten que el parámetro de plantilla de f
sea una referencia, pero no el de g
?
davy.ai
La diferencia radica en las reglas de deducción de tipo para las plantillas. Cuando se llama a
f
con un argumento lvalue comoint a{}; f(a)
, entran en juego las reglas de deducción de tipo para referencias de reenvío, lo que resulta en queT
se deduzca comoint&
. Por otro lado, cuando se llama af
con un argumento rvalue comof(5)
, también entran en juego las reglas de deducción de tipo para referencias de reenvío, lo que resulta en queT
se deduzca comoint
.En el caso de
g
, no hay ninguna referencia de reenvío involucrada. En su lugar,T
se deduce simplemente en función del tipo del argumento pasado ag
. Sig
se llama con un argumento lvalue comoint a{}; g(a)
,T
se deduce comoint
. Sig
se llama con un argumento rvalue comog(5)
,T
también se deduce comoint
.En resumen, las reglas para referencias de reenvío permiten que el parámetro de plantilla de
f
sea una referencia o no referencia, dependiendo del tipo del argumento pasado a la función, mientras que el parámetro de plantilla deg
siempre se deduce en función del tipo del argumento pasado a la función.