tipos teorico programas programa practico plantillas paso lenguaje ejemplos c++ templates c++11 universal-reference

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&