¿Tiene sentido esta regla de análisis estático de C ++ como está?

Estoy implementando algunas reglas de análisis estático de C ++, y una de ellas prohíbe que una función devuelva una referencia o un puntero a un parámetro de referencia de la función, es decir, todas las siguientes no son compatibles:

int *f(int& x) { return &x; } // #1
const int *g(const int& x) { return &x; } // #2
int& h(int& x) { return x; } // #3
const int& m(const int& x) { return x; } // #4

La justificación dada para esto es que "Es un comportamiento definido por la implementación si el parámetro de referencia es un objeto temporal o una referencia al parámetro".

Sin embargo, esto me desconcierta, porque los operadores de flujo en C ++ están escritos de esta manera, por ejemplo.

std::ostream& operator<<(std::ostream& os, const X& x) {
    //...
    return os;
}

Creo que estoy bastante seguro de que los operadores de flujo en C ++ no muestran, en general, un comportamiento definido por la implementación, así que, ¿qué está pasando?

De acuerdo con mi entendimiento actual, espero que los números 1 y 3 estén bien definidos, sobre la base de que los temporales no pueden estar vinculados a referencias no constantes, por lo queint& x se refiere a un objeto real que tiene una duración más allá del alcance de la función, por lo tanto, devolver un puntero o una referencia a ese objeto está bien. Espero que # 2 sea poco fiable, porque un temporal podría haber estado vinculado aconst int& x, en cuyo caso tratar de tomar su dirección parecería un mal plan. No estoy seguro acerca del # 4; mi intuición es que eso también es potencialmente peligroso, pero no estoy seguro. En particular, no tengo claro qué pasaría en el siguiente caso:

const int& m(const int& x) { return x; }
//...
const int& r = m(23);

Respuestas a la pregunta(2)

Su respuesta a la pregunta