This is a revision of
N2629. The only change is moving the most recent error storage to
basic_streambuf from the derived class, eliminating the need for an
added virtual function and simplifying the proposal.

Lack of detailed error reporting has long been a concern about the C++ I/O
Streams library. For example, The C++ Standard Library by Nicolai
Josuttis, complained in 1999:

Unfortunately, the standard does not require that the exception object
includes any information about the erroneous stream or the kind of error.

The problem is particularly acute for failures to open a file. Such failures
are extremely common and there are numerous possible reasons for failure, such
as the file not being found, the permissions being wrong, and so forth.
Diagnosing these failures without knowing the exact reason for failure is
difficult, irritating, and time wasting.

The standard library now supplies support for portable reporting of
errors from the host operating system or other low-level API's that are
typically used to implement file based I/O streams. See 19.4 System error
support [syserr]. Errors may be reported by either an error code or by an
exception containing an error code. Additional categories of errors, such as
those arising from the I/O streams themselves are also supported.

Failures from the current iostreams library may be reported by either setting I/O state
bits or by throwing an 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 std::system_error
so that a detailed error code is available.

Failures detected by checking I/O state bits are augmented by keeping the
last error code as part of the I/O state and making it available via an
basic_ios::error function returning a const std::error_code&.
Additional setter and getter functions ensure that buffers and derived classes
can set/get the error code appropriately. Additional overloads to existing
functions ensure backward compatibility.

Much of the proposal is an add-on, and so will have no impact on existing
code. In the few cases where signatures or semantics of existing functions
change, default behavior is carefully chosen to eliminate breakage of existing
code.

The one known case where existing code might break is user code that
depends on ios_base::failure having specific derivation. Library
clause 17.4.4.7 has always granted implementors permission to derive classes
from classes other than the specified base, so such code is already suspect.

The proposal does break ABI compatibility in that a new virtual function is
added and exception derivation changes.

A C++03 proof-of-concept prototype of the proposal has been implemented by modifying the
Apache C++ Standard Library. No
difficulties were encountered and coding was straightforward. The effort took
about a day and a half by someone who had no prior exposure to the
implementation and was designing the interface during implementation. Virtually all changes
were on paths through the code that are only executed when a failure has
already been detected.

The specification of std::system_error as a base class of
std::basic_ios::failure was originally proposed in
N2503, Indicating iostream failures with system_error. Library
working group (LWG) discussion at the February, 2008, Bellevue meeting sparked
the current proposal.

Martin Sebor suggested moving the most recent error storage to
basic_streambuf from the derived class. Daniel Krügler identified mistakes and inconsistencies in a draft of
the initial version of this proposal, and suggested many useful fixes. Alisdair Meredith initiated the
original
N2503 proposal.

The proposed wording assumes
Library issues 805, posix_error::posix_errno concerns, and 832,
Applying constexpr to System error support, have been accepted and applied
to the working paper. If either of these has not been accepted, minor changes
to the wording of this proposal will be required.

io_category shall
point to a statically initialized
object of a type derived from class error_category.

The object’s default_error_condition and
equivalent virtual functions shall behave as specified for the class
error_category. The object’s name virtual function
shall return a pointer to the string "IO".

At a location to be determined, add:

constexpr error_code make_error_code(ioerrc e);

Returns:error_code(static_cast<int>(e), io_category).

constexpr error_condition make_error_condition(ioerrc e);

Returns:error_condition(static_cast<int>(e), io_category).

At a location to be determined, add:

Functions in this clause specified to call the setstate function to set
failbit or badbit error flags shall ensure that subsequent calls to
error() return a reference to an error_code object that identifies the error. The
error_code object shall either have a category of io_category, or be an
error_code object returned by rdbuf()->puberror().

Effects: Constructs an object of class basic_streambuf<charT,traits>
and initializes:
— all its pointer member objects to null pointers,
— the getloc()
member to a copy the global locale, locale(), at the time of construction.— the error() member to
error_code(ioerrc::streambuf, ioerror_category).

Remarks: Once the getloc()
member is initialized, results of calling locale member functions, and of
members
of facets so obtained, can safely be cached until the next time the member imbue
is called.

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.

Implementations are encouraged to report
basic_ios::error() as the ec argument when throwing ios_base::failure
exceptions. [Note: The default value of ec is
provided to ensure code written before the addition of the second argument
continues to work. It is the least desirable of possible values; more specific
values ease error diagnosis. -- end note]