2010-09-22 11 views
16

Al tratar de resolver this problem, algo me hizo preguntarme. Consideremos el siguiente código:¿Colapso de referencia?

template <typename T> 
struct foo 
{ 
    foo(T const& x) : data(x) {} 
    T data; 
}; 

Parece que puedo construir un objeto de tipo foo<T const&> sin error, el hipotético T const& const& entendiéndose como T const&.

Parece que esto se llama referencia colapsando, pero nunca escuché este término antes (ver comentarios en la pregunta relacionada).

¿Está esto extendido? ¿Es este estándar?

+0

+1. Tengo algunos deberes para hacer en esto, thx –

+0

Me gustaría vincular esta pregunta similar: http://stackoverflow.com/questions/4144234/c-template-instantiation-with-reference-type –

Respuesta

19

En C++ 03, no era legal para hacer lo siguiente

typedef int &ref; 
ref &r = ...; // reference to reference! 

Esto provoca con frecuencia problemas para las personas que compilan con muy estricta o más viejos Los compiladores de C++ 03 (GCC4.1 y Comeau 8/4/03 no les gusta lo anterior) porque los enlazadores de objetos de función estándar no se ocupan de la situación de "referencia a referencia" y ocasionalmente crean esos tipos ilegales.

En C++ 0x esto se llama "colapso de referencia", sí. La mayoría de los compiladores actuales de C++ 03 hacen eso (es decir, T& donde T denota un tipo de referencia es T nuevamente), mediante la aplicación retroactiva de la regla. La biblioteca boost.call_traits hace que sea fácil declarar dichos parámetros de función, para que no ocurra la situación de "referencia a referencia".

Tenga en cuenta que el const no tiene ningún efecto. Un const aplicado en un tipo de referencia se ignora silenciosamente. Entonces, incluso si el compilador admite el colapso de referencia, lo siguiente no es legal

int const x = 0; 

// illegal: trying to bind "int&" to "int const"! 
ref const& r = x; 
+0

Genial, me di cuenta de que esto podría ser resuelto por clases de rasgos, pero nunca he visto algo así en [mi implementación de] STL. –

+0

¿No debería ser eso "es decir, un' T & 'donde' T' denota que un tipo de referencia es 'T &' again "? – fredoverflow

+0

@Fred que sería auto recursivo. Quiero decir, si 'T' es' U & ', y dices' T & ', el tipo de resultado es' T' - es decir 'U &'. Por supuesto, esto no es compatible con las referencias de rvalue. Tendría que decir "es decir, un' T & 'donde' T' denota un tipo 'U & -o - &&' denota el tipo 'U &' ", para ser correcto con rvalue refs. –

5

Según this, en C++ 98 sólo había un apoyo limitado a colapso de referencia:

En C++ 98, sólo hay una referencia regla colapso: T & & o una referencia con una referencia, se derrumba a T &:

void g(int & ri) {++ri;} // int& & -> int& 
void f(int & ri) {g(ri);} 

Incluso allí, es ilegal para tratar de declar ea variable que es una referencia a una referencia:

int ben; 
int& bill(ben);  // OK 
int & & bob(bill); // error C2529: 'bob' : reference to reference is illegal 
+2

No hay referencia de colapso en C++ 03. El autor de ese artículo está equivocado. El tipo de una expresión de identidad que utiliza el nombre de una referencia no es un tipo de referencia. * La expresión No * tiene tipo de referencia. Las expresiones tienen categorías de valor que deciden cómo pueden vincularse a las referencias. – Potatoswatter

+0

@Potatoswatter - gracias, y también hay mejores referencias ahora. Eliminaré esta parte. –

+0

Gracias ... pero hmm, ese enlace no es el que seguí antes. – Potatoswatter

Cuestiones relacionadas