teorico - Comportamiento de la función de plantilla de C++
programa c++ (3)
Debido a que hay una deducción de argumento de plantilla, se produce un colapso de referencia. Es lo que Scott Meyers llama referencias universales . El U&&
se convertirá en int &
. Hay un buen artículo y un video sobre cómo funciona y cómo podría usarse.
Digamos que tengo esta función:
bool f(int&& one, int&& two) { }
Si intento llamarlo con este código:
int x = 4;
f(x, 5);
el compilador se quejará de que no puede convertir x de lvalue reference a rvalue reference, lo cual es correcto.
Ahora si convierto f en una función de plantilla como esta:
template <class T, class U>
bool f(T&& one, U&& two) { }
entonces puedo llamarlo con una referencia lvalue:
int x = 5;
f(x, 5);
¿Por que es esto entonces? ¿Por qué el compilador no se queja en este caso?
Esto sucede debido a las reglas de colapso de referencia agregadas en c ++ 11
A& & becomes A&
A& && becomes A&
A&& & becomes A&
A&& && becomes A&&
En las plantillas, estas reglas se aplican pero no en una función normal, no hay una referencia que colapse normalmente en la función. Existen otras situaciones específicas en las que se producirá un colapso de referencia, como en presencia de auto
, decltype
o typedef
(que incluye el using
declaraciones) que explica los resultados de su compilación. El colapso de referencias tuvo que agregarse en c ++ 11 porque, de lo contrario, utilizar referencias como A & & se convertiría en errores, ya que no se puede tener una referencia a una referencia.
Según § 8.3.3 / 6. Es la regla de colapso de referencia.
template <class T> void func(T&&) // Accepts rvalue or lvalue
void func(T&&) // Accepts rvalue only
void func(T&) // Accepts lvalue only
Vale la pena ejemplo de borrador estándar:
int i;
typedef int& LRI;
typedef int&& RRI;
LRI& r1 = i; // r1 has the type int&
const LRI& r2 = i; // r2 has the type int&
const LRI&& r3 = i; // r3 has the type int&
RRI& r4 = i; // r4 has the type int&
RRI&& r5 = 5; // r5 has the type int&&
decltype(r2)& r6 = i; // r6 has the type int&
decltype(r2)&& r7 = i; // r7 has the type int&