c++ - tipos - Comprueba si la referencia de flujo es NULL ya no se compila
tipos de errores en visual basic (3)
El código no compara la referencia con NULL , sino que compara el objeto de referencia con NULL . Las referencias no pueden ser NULL , y es imposible comparar la referencia con NULL .
Y
Este proyecto compilé i cuando lo usé hace mucho tiempo atrás con el antiguo gnu toolchain.
Porque el comportamiento cambió desde C ++ 11.
Antes de C ++ 11, std::ostream podría convertirse implícitamente a void* través del operador void * () , que devuelve un puntero nulo si se produce un error en la transmisión. Por lo tanto, la intención original del código es verificar si la transmisión no tiene errores.
Desde C ++ 11, la función de conversión se cambió al explicit operator bool() , que devuelve false si se produce un error. Tenga en cuenta que la función está declarada como explicit , lo que significa que la conversión implícita a bool no está permitida, por lo que el código no se compilará con C ++ 11 nuevamente porque std::ostream no se puede convertir a bool implícitamente (y luego se compara) con NULL (un literal entero)).
Con un compilador compatible con C ++ 11 puede cambiar el código a
if (m_stream) {
m_stream.flush();
}
Tenga en cuenta que para las conversiones contextuales se consideran incluso las funciones de conversión explícitas. Para el código anterior, m_stream se convertirá a bool mediante explicit operator bool() , entonces el valor se usaría para la condición de if .
Estoy compilando un proyecto desactualizado con mis últimos compiladores gcc g ++, (versión> 6)
Hay una clase CodeWriter con una variable de referencia ostream .
class CodeWriter
{
//private:
protected:
ostream &m_stream;
public:
CodeWriter(ostream &stream):m_stream(stream){}
~CodeWriter(){
if(m_stream != NULL){
m_stream.flush();
}
}
};
La clase es bastante grande, así que solo incluí las variables y funciones relevantes.
Como puede ver, el destructor parece estar comparando la referencia con NULL . Este proyecto se compiló bien cuando lo usé hace mucho tiempo con el antiguo gnu toolchain.
Pero ahora está lanzando un error que dice que no hay un operator != coincidente operator != Para comparar ostream y long int .
¿Alguien puede explicar la razón detrás del cambio y cómo puedo solucionarlo?
Estaré encantado de proporcionar información adicional / incluir a toda la clase si es necesario.
Las clases de flujo tenían un operator void*() en una de las clases base en pre-C ++ 11. Por supuesto, el valor void* podría compararse con NULL .
En C ++ actual, en cambio, es un explicit operator bool() que funciona en el contexto de la sentencia if , pero no en una expresión general.
El uso de un void* fue para evitar algunas conversiones no deseadas de bool que ocurrían cuando no teníamos operadores explicit .
Las transmisiones siempre se pueden evaluar en un contexto booleano, así que simplemente cámbielo a:
if (m_stream) {
m_stream.flush();
}
C ++ 11 hizo la conversión a bool explicit . Esto es equivalente a if (!m_stream.fail()) . Antes de C ++ 11, esta capacidad de comprobación a corto plazo se logra al proporcionar una conversión (implícita) a void* , por lo que su código anterior solía funcionar.
La razón por la que el código está verificando esto, en lugar de simplemente llamar a m_stream.flush(); directamente, es posible que la secuencia pueda tener excepciones habilitadas para fallas y que puedan lanzar, [actualizar:] pero, como señaló @Arne, la flush sí misma puede fallar y lanzar también. Si no hay excepciones, solo puede omitir la verificación booleana por completo. [/ Actualizar]