De este artículo del blog de Visual C ++ sobre las referencias de rvalue :
... C ++ no quiere que modifiques accidentalmente los temporales, pero llamar directamente a una función miembro no constante en un valor variable modificable es explícito, por lo que está permitido ...
Básicamente, no deberías intentar modificar los temporales por el solo hecho de que son objetos temporales y morirán en cualquier momento. La razón por la que puede llamar a métodos no constantes es que, bueno, puede hacer algunas cosas "estúpidas" siempre y cuando sepa lo que está haciendo y sea explícito al respecto (por ejemplo, usando reinterpret_cast). Pero si vincula una referencia temporal a una referencia no constante, puede seguir pasándola "para siempre" solo para que su manipulación del objeto desaparezca, porque en algún momento del camino olvidó por completo que esto era temporal.
Si yo fuera usted, repensaría el diseño de mis funciones. ¿Por qué g () acepta referencia, modifica el parámetro? Si no, haga referencia constante, en caso afirmativo, ¿por qué intenta pasarle temporalmente? ¿No le importa que sea una modificación temporal? ¿Por qué getx () regresa temporalmente de todos modos? Si comparte con nosotros su escenario real y lo que está tratando de lograr, puede obtener algunas buenas sugerencias sobre cómo hacerlo.
Ir en contra del lenguaje y engañar al compilador rara vez resuelve problemas, por lo general crea problemas.
Editar: Abordar preguntas en el comentario: 1)
X& x = getx().ref(); // OK when will x die?
- No lo sé y no me importa, porque esto es exactamente lo que quiero decir con "ir en contra del idioma". El lenguaje dice que "los temporales mueren al final de la declaración, a menos que estén obligados a hacer referencia constante, en cuyo caso mueren cuando la referencia queda fuera de alcance". Aplicando esa regla, parece que x ya está muerto al comienzo de la siguiente declaración, ya que no está obligado a const referencia (el compilador no sabe qué devuelve () devuelve). Sin embargo, esto es solo una suposición.
2) Indiqué claramente el propósito: no está permitido modificar temporarios, porque simplemente no tiene sentido (ignorando las referencias de valor de C ++ 0x). La pregunta "entonces, ¿por qué se me permite llamar a miembros que no son constantes?" es buena, pero no tengo una mejor respuesta que la que dije anteriormente.
3) Bueno, si estoy en lo cierto al X& x = getx().ref();
morir x al final de la declaración, los problemas son obvios.
De todos modos, según su pregunta y comentarios, no creo que incluso estas respuestas adicionales lo satisfagan. Aquí hay un último intento / resumen: el comité de C ++ decidió que no tiene sentido modificar los temporales, por lo tanto, rechazaron la vinculación a referencias no constantes. Puede haber alguna implementación del compilador o también hubo problemas históricos, no lo sé. Luego, surgió un caso específico, y se decidió que, contra todo pronóstico, todavía permitirán la modificación directa mediante la llamada al método no constante. Pero eso es una excepción: generalmente no se le permite modificar los temporales. Sí, C ++ es a menudo así de raro.