C++ exception specification for iostream operator overloading
Asked Answered
I

2

6

It is not specified if call to ostream operator<< can fail or throw any exception and I have never encounter this.

  1. Is there a case where ostream operator<< could fail ?
  2. If no, why standard does not put noexcept specifier to these overloads ?
  3. Is the following overload valid ? good practice ? commonly used ?
  4. Same question for istream operator>> ?
struct MyClass {
    int data;
    // I/O operators with noexcept specifier
    friend std::istream& operator>>(std::istream &in, MyClass &obj) noexcept;
    friend std::ostream& operator<<(std::ostream &out, const MyClass &obj) noexcept;
};
Illdisposed answered 7/11, 2019 at 15:50 Comment(0)
S
8

The reason none of the operator >> and operator << are marked as noexcept is because of std::basic_ios::exceptions. This member function is present in all objects that inherit from std::basic_ios and allows you to configure the stream to throw exceptions for certain failure modes. If the operators were noexcept then you could not use them with a stream that has exceptions set.

Stork answered 7/11, 2019 at 15:54 Comment(7)
This feels like it only answers the 2nd question adequately. Then again, an OP shouldn't put a lot of questions in the same question, so there's that.Overblouse
@Chipster To me, If the operators were noexcept then you could not use them with a stream that has exceptions set covers all of the questions. UB is a good reason not to do something.Stork
It doesn't answer question 1, I don't think. The OP seems to want an example. But I suppose that's just me.Overblouse
@Chipster Do I really need to show a stream getting the exception set to show how an exception can be thrown when it hit an error?Stork
I guess not. Would be nice though. You have a point, though, so I'll upvote anyway.Overblouse
I think std::basic_ios::exceptions answers questions 1, 2 & 4. Indeed, as I understand, standard iostream operators can throw in file read/write context. Nevertheless, what prevents the user to handle exceptions in operator overload ? --> question 3 is still accurate.Illdisposed
@Illdisposed You could handle exceptions in your own type but if you can't overload the operators for built in types so there is no way to catch from inside the function for those types, hence those operators being not noexcept. The whole purpose of enabling exceptions is you want them to fire and surface to your code.Stork
B
2
  1. It can fail and you can either use return values for knowing the result or enable exceptions with std::ostream::exceptions method.

The example is for std::iostream.

#include <iostream>

int main () {

    std::cout.exceptions ( std::ios::failbit | std::ios::badbit );

    try {

        // operations with the stream ...
    
    } catch (const std::ios::failure & ex) {

    }
 
}
  1. They generally can.

  2. It is valid, but you must guarantee exceptions are not thrown out of them in fact. If an exception is attempted to be thrown out from the methods you provided, std::terminate will be called, since it is what happens for functions declared with noexcept when an exception is leaving them.

  3. The same is for std::istream.

Beaverbrook answered 24/8, 2021 at 21:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.