Para rechazar el primer fragmento de código, el compilador aplica la regla simple de que no se puede vincular directamente una referencia temporal a una referencia no constante.
Para rechazar el segundo, el compilador tal vez podría aplicar una regla que la declaración return
de una función que devuelve por referencia no puede ser el nombre de una variable automática (incluido un parámetro de función by-value). Eso me parece una regla bastante fácil también.
No sé por qué el estándar no especifica que hacerlo está mal formado. No puedo pensar en ningún uso válido para él, pero quizás en el momento del primer estándar habría creado una carga excesiva en alguna implementación u otra. O tal vez se pensó que era solo la mitad de una solución y no valía la pena molestarse (hay muchas otras formas de crear una referencia que cuelga, esto solo bloquea una de ellas).
La razón por la que el estándar no lo detiene en general para crear una referencia no const vinculada a un temporal es que hay ocasiones en las que está bien. Por ejemplo:
struct Foo {
static void set(Foo &f) { f.val = 0; }
int val;
int bar() {
set(*this);
return val;
}
};
std::cout << Foo().bar() << "\n";
Aquí Foo()
es una temporal, y la línea de set(*this)
se une a una referencia no const (pero no directamente, se utiliza una expresión lvalue *this
que se refiere a un temporal algunas veces, pero no otros) . Aquí no hay ningún problema, el temporal sobrevive a la referencia. Por lo tanto, sería innecesariamente restrictivo para el lenguaje el evitar de alguna manera que cualquier temporal se vincule a una referencia que no sea const.
Esto es UB (bueno, accediendo a la referencia, de todos modos) y cualquier compilador en serio le avisará al respecto. –