referencias constantes con typedef y plantillas en c ++

Escuché que los objetos temporales solo se pueden asignar a referencias constantes.

Pero este código da error

#include  template t const& check(){ return t(); //return a temporary object } int main(int argc, char** argv){ const int &resCheck = check(); /* fine */ typedef int& ref; const ref error = check(); / *error */ return 0; } 

El error que se obtiene es la invalid initialization of reference of type 'int&' from expression of type 'const int'

Esta:

 typedef int& ref; const ref error; 

No hace lo que crees que hace. Considere en su lugar:

 typedef int* pointer; typedef const pointer const_pointer; 

El tipo de const_pointer es int* const , no const int * . Es decir, cuando dices const T estás diciendo “haz un tipo donde T sea inmutable”; entonces en el ejemplo anterior, el puntero (no el punto) se hace inmutable.

Las referencias no pueden hacerse const o volatile . Esta:

 int& const x; 

no tiene sentido, por lo que agregar cv-calificadores a las referencias no tiene ningún efecto.

Por lo tanto, el error tiene el tipo int& . No se puede asignar un const int& a él.


Hay otros problemas en tu código. Por ejemplo, esto es ciertamente incorrecto:

 template t const& check() { return t(); //return a temporary object } 

Lo que estás haciendo aquí es devolver una referencia a un objeto temporal que finaliza su vida útil cuando la función retorna . Es decir, obtienes un comportamiento indefinido si lo usas porque no hay ningún objeto a la vista. Esto no es mejor que:

 template t const& check() { T x = T(); return x; // return a local...bang you're dead } 

Una mejor prueba sería:

 template T check() { return T(); } 

El valor de retorno de la función es temporal, por lo que aún puede probar que puede vincular temporarios a referencias constantes.

Es un error muy común para las personas de habla inglesa, debido a la forma en que funciona la gramática inglesa.

Considero que es extremadamente desafortunado que la syntax de C ++ permita ambos:

 const int // immutable int int const // immutable int 

tener el mismo significado

No lo hace más fácil, realmente, y no se puede componer ya que:

 const int* // mutable pointer to immutable int int* const // immutable pointer to mutable int 

ciertamente NO tienen el mismo significado.

Y esto, desafortunadamente para ti, lo que sucede aquí, como explica @GMan.

Si desea evitar este tipo de error en el futuro, tome la costumbre de calificar sus tipos ( const y volatile ) a su derecha , entonces podrá tratar un typedef como un simple reemplazo de texto.

Su código da error porque el calificador const en el const ref error simplemente se ignora porque 8.3.2/1 dice

Las referencias calificadas de Cv están mal formadas, excepto cuando los cv-calificadores se introducen mediante el uso de un typedef (7.1.3) o de un argumento de tipo de plantilla (14.3), en cuyo caso los cv-qualifiers son ignorados .

Entonces el error tiene tipo int& no const int& .

Para mantener la coherencia con la regla de la derecha , prefiero usar los calificadores ‘cv’.

 int const x = 2; // x is a const int (by applying Right Left rule) int const *p = &x; // p is a pinter to const int 

En su ejemplo, escribiría const ref error = check(); al igual que

 ref const error = check(); // parsed as error is a const reference to an integer 

Como señaló @Prasoon Saurav, los calificadores cv se ignoran cuando se introducen a través de typedef porque, como dice @GMan, las referencias calificadas de cv están mal formadas.

Por lo tanto, la statement es efectivamente la siguiente, que, por supuesto, es un error.

  int &error = check(); 

Mira esto para más información.

Esto está comstackdo:

 typedef const int & ref; 
 ref error = check  (); 

El comstackdor de VC ++ da alguna explicación de su error: calificador aplicado al tipo de referencia; ignorado El tipo de referencia se debe declarar como constante, const no se puede aplicar más tarde.