Document Number: N2503=08-0013
2008-02-04
Alisdair Meredith <alisdair.meredith@codegear.com>
Beman Dawes <bdawes@acm.org>

Indicating iostream failures with system_error

Problem Description

The standard library now supplies library support for portable reporting of errors from the host operating system. See 19.4.5 Class system_error [syserr.syserr]. That API allows exception classes used to report host system failures to be derived from a new library exception type, system_error, which encapsulates failure information returned from the host operating system.

Failures in the iostreams portion of the standard library may indicate failure with exceptions. The exception thrown in such cases is ios_base::failure, which is publicly derived from the standard library class exception.

As iostream failures are typically a runtime problem detected by the host system, we would like this exception to derive from system_error.

Proposed Solution

Library clause 17.4.4.7 grants implementors permission to derive classes from classes other than the specified base, so long as

  • the additional 'intermediate' classes ultimately derive from the specified base
  • the name of any 'intermediate' class is reserved to the implementation
  • Note that all standard library class names are by definition reserved for the implementation. In particular, system_error and runtime_error are names reserved for the implementation so a conforming (but surprising) implementation of ios_base::failure in C++03 might derive from runtime_error.

    Therefore, it is proposed that ios_base::failure derive from system_error and that the implementation makes a best effort to record the fault reported by the host system.

    Alternative Proposal

    Note that Benjamin Kosnik proposes a more extensive reworking of standard library exceptions in n2309.

    Proposed Changes to the Working Paper

    Change 27.4.2.1.1 [ios::failure] as indicated:

    
    namespace std {
      class ios_base::failure : public exceptionsystem_error {
      public:
        explicit failure(const string& msg, error_code ec = posix_error::io_error );
        explicit failure(const char* msg, error_code ec = posix_error::io_error );
        failure(const string& msg, error_code::value_type ev, const error_category& ecat );
        failure(const char* msg, error_code::value_type ev, const error_category& ecat );
        virtual const char* what() const throw();
      };
    }

    The class failure defines the base class for the types of all objects thrown as exceptions, by functions in the iostreams library, to report errors detected during stream buffer operations.

    explicit failure(const string& msg, error_code ec = posix_error::io_error);

    Effects: Constructs an object of class failure.

    Postcondition: code() == ec and strcmp(what(), msg.c_str()) == 0

    explicit failure(const char* msg, error_code ec = posix_error::io_error);

    Effects: Constructs an object of class failure.

    Postcondition: code() == ec and strcmp(what(), msg ) == 0

    failure(const string& msg, error_code::value_type ev, const error_category& ecat);

    Effects: Constructs an object of class failure.

    Postcondition: code() == error_code(ev, ecat) and strcmp(what(), msg.c_str()) == 0

    failure(const char* msg, error_code::value_type ev, const error_category& ecat);

    Effects: Constructs an object of class failure.

    Postcondition: code() == error_code(ev, ecat) and strcmp(what(), msg) == 0

    
        

    Change 27.4.4.3p5 [iostate.flags] as indicated:

    Effects: If ((state | (rdbuf() ? goodbit : badbit)) & exceptions()) == 0, returns. Otherwise, the function throws an object fail of class basic_ios::failure (27.4.2.1.1), constructed with implementation defined argument values.

    Note: Implementations are encouraged to report the original failure from the host system as the error code when throwing an exception.