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