Con edad (es decir: no mucho después cfront
) compiladores de C++, el compilador no estaba garantizada para llamar implícitamente operadores encasillado en los objetos cuando sea necesario. Si iostream
no tiene un operator !
declarado, entonces no se puede esperar que !cout
funcione en todos los casos. C++ 89 (o lo que sea que se llamó el estándar anterior a C++ 98) simplemente dejó el área indefinida.
Esta es también la razón por la que operator void*()
estaba sobrecargado, y no o operator bool
. (bool
ni siquiera existía como su propio tipo en el estándar en ese punto.) Recuerdo que mi profesor me dijo que if()
, bajo el capó, esperaba un void*
en C++, porque ese tipo podría actuar como un tipo de "superconjunto" relativo a esos tipos de resultados de expresión que se pasarían a una declaración if
, pero no he encontrado esto explicado en ninguna parte.
Esto fue alrededor del tiempo de gcc 2, cuando la mayoría de la gente no soportaba plantillas o excepciones, o si lo hacían, no las soportaba completamente, por lo que la metaprogramación C++ con plantillas era todavía un ejercicio teórico y se aseguraba para comprobar que operator new
no devolvió un puntero nulo.
Esto me volvió loco durante varios años.
Un extracto interesante de Stroustrup's The C++ Programming Language, 3rd ed. (1997), página 276:
El istream y ostream tipos se basan en una función de conversión para permitir declaraciones como
while (cin >> x) cout << x;
La entrada de operación cin >> x devuelve unistream &. Ese valor se convierte implícitamente en un valor que indica el estado de cin. El valor puede entonces probarse por mientras. Sin embargo, normalmente es no una buena idea para definir una conversión implícita de un tipo a otro de tal manera que la información se pierda en la conversión.
Hay mucho en C++ que parece ser una victoria de lo lindo o lo inteligente sobre lo consistente. No me importa si un bit C++ fue lo suficientemente inteligente como para manejar el bucle anterior como:
while (!(cin >> x).fail()) cout << x;
debido a esto, mientras más detallado y más puntuacion, es más claro que un programador principiante.
... En realidad, ahora que lo pienso, no me gustan ninguno de esos constructos. Deletérelo:
for(;;)
{ cin >> x;
if(!cin)
break;
cout << x;
}
¿Por qué me gusta esto mejor? Porque esta versión hace que sea mucho más claro cómo expandir el código para, por ejemplo, manejar dos lecturas a la vez en lugar de una. Por ejemplo, "El código existente copia una secuencia de valores flotantes. Queremos que lo modifiques de modo que combine los valores flotantes y los escriba, dos por línea, porque ahora estamos usando números complejos".
Pero estoy divagando.
Estas son funciones miembro de 'basic_ios', no' ios_base'. –
@Marcelo: Gracias, lo arreglé. – sbi
@Neil: Gracias, me olvidé de eso. De todos modos, parece que tampoco lo sabes? – sbi