I am compiling an outdated project with my latest gcc g++ compilers, (version > 6)
There is a class CodeWriter
with an ostream
reference variable.
class CodeWriter { //private: protected: ostream &m_stream; public: CodeWriter(ostream &stream):m_stream(stream){} ~CodeWriter(){ if(m_stream != NULL){ m_stream.flush(); } } };
The class is quite large so I included only the relevant variables and functions.
As you can see the destructor seems to be comparing the reference to NULL
. This project compiled fine when I used it long back with old gnu toolchain.
But now it is throwing an error saying that there is no matching operator !=
to compare ostream
and long int
.
Can anyone explain the rationale behind the change, and how I can fix this?
I would be happy to provide additional information/ include the whole class if required.
The code is not comparing the reference itself with NULL
, but comparing the referenced-object with NULL
. References can't be NULL
, and it's impossible to compare the reference itself with NULL
.
And
This project compiled i when i used it long back with old gnu toolchain.
Because the behavior changed since C++11.
Before C++11, std::ostream
could be implicitly converted to void*
via operator void*(), which returns a null pointer if error has occurred on the stream. So the original intent of the code is to check whether the stream has no errors.
Since C++11 the conversion function was changed to explicit operator bool()
, which returns false
if error has occured. Note the function is declared as explicit
, which means implicit conversion to bool
is not allowed, so the code won't compile with C++11 again because std::ostream
can't be converted to bool
implicitly (and then to be compared with NULL
(an integer literal)).
With a C++11-compatible compiler you can just change the code to
if (m_stream) { m_stream.flush(); }
Note that for contextual conversions even explicit conversion functions are considered. For the above code, m_stream
will be converted to bool
via explicit operator bool()
, then the value would be used for the condition of if
.
Streams can always be evaluated in a boolean context, so just change it to:
if (m_stream) { m_stream.flush(); }
C++11 made the conversion to bool explicit
. This is equivalent to if (!m_stream.fail())
. Prior to C++11, this short-hand checkability was achieved by providing an (implicit!) conversion to void*
, which is why your old code used to work.
The reason the code is checking for this, rather than just calling m_stream.flush();
directly, is perhaps that the stream may have exceptions enabled for failure and that might throw, [update:] but, as @Arne pointed out, flush
itself may fail and throw, too. If there are no exceptions, you can just skip the boolean check entirely.[/update]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With