Title
Improving <system_error> initialization
Status
c++11
Section
[syserr.errcat]
Submitter
Beman Dawes

Created on 2008-09-14.00:00:00 last changed 162 months ago

Messages

Date: 2010-10-21.18:28:33

Proposed resolution:

Change [value.error.codes] Value of error codes as indicated:

Certain functions in the C++ standard library report errors via a std::error_code (19.4.2.2) object. That object's category() member shall return a reference to std::system_category() for errors originating from the operating system, or a reference to an implementation-defined error_category object for errors originating elsewhere. The implementation shall define the possible values of value() for each of these error categories. [Example: For operating systems that are based on POSIX, implementations are encouraged to define the std::system_category() values as identical to the POSIX errno values, with additional values as defined by the operating system's documentation. Implementations for operating systems that are not based on POSIX are encouraged to define values identical to the operating system's values. For errors that do not originate from the operating system, the implementation may provide enums for the associated values --end example]

Change [syserr.errcat.overview] Class error_category overview error_category synopsis as indicated:

const error_category& get_generic_category();
const error_category& get_system_category();

static storage-class-specifier const error_category& generic_category = get_generic_category();
static storage-class-specifier const error_category& system_category = get_system_category();

Change [syserr.errcat.objects] Error category objects as indicated:

const error_category& get_generic_category();

Returns: A reference to an object of a type derived from class error_category.

Remarks: 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 "GENERIC".

const error_category& get_system_category();

Returns: A reference to an object of a type derived from class error_category.

Remarks: The object's equivalent virtual functions shall behave as specified for class error_category. The object's name virtual function shall return a pointer to the string "system". The object's default_error_condition virtual function shall behave as follows:

If the argument ev corresponds to a POSIX errno value posv, the function shall return error_condition(posv, generic_category()). Otherwise, the function shall return error_condition(ev, system_category()). What constitutes correspondence for any given operating system is unspecified. [Note: The number of potential system error codes is large and unbounded, and some may not correspond to any POSIX errno value. Thus implementations are given latitude in determining correspondence. — end note]

Change [syserr.errcode.constructors] Class error_code constructors as indicated:

error_code();

Effects: Constructs an object of type error_code.

Postconditions: val_ == 0 and cat_ == &system_category().

Change [syserr.errcode.modifiers] Class error_code modifiers as indicated:

void clear();

Postconditions: value() == 0 and category() == system_category().

Change [syserr.errcode.nonmembers] Class error_code non-member functions as indicated:

error_code make_error_code(errc e);

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

Change [syserr.errcondition.constructors] Class error_condition constructors as indicated:

error_condition();

Effects: Constructs an object of type error_condition.

Postconditions: val_ == 0 and cat_ == &generic_category().

Change [syserr.errcondition.modifiers] Class error_condition modifiers as indicated:

void clear();

Postconditions: value() == 0 and category() == generic_category().

Change [syserr.errcondition.nonmembers] Class error_condition non-member functions as indicated:

error_condition make_error_condition(errc e);

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

Change [iostreams.base] Iostreams base classes, Header <ios> synopsis as indicated:

concept_map ErrorCodeEnum<io_errc> { };
error_code make_error_code(io_errc e);
error_condition make_error_condition(io_errc e);
storage-class-specifier const error_category& iostream_category();

Change [ios::failure] Class ios_base::failure, paragraph 2 as indicated:

When throwing ios_base::failure exceptions, implementations should provide values of ec that identify the specific reason for the failure. [ Note: Errors arising from the operating system would typically be reported as system_category() errors with an error value of the error number reported by the operating system. Errors arising from within the stream library would typically be reported as error_code(io_errc::stream, iostream_category()). — end note ]

Change [error.reporting] Error reporting as indicated:

error_code make_error_code(io_errc e);

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

error_condition make_error_condition(io_errc e);

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

storage-class-specifier const error_category& iostream_category();

The implementation shall initialize iostream_category. Its storage-class-specifier may be static or extern. It is unspecified whether initialization is static or dynamic (3.6.2). If initialization is dynamic, it shall occur before completion of the dynamic initialization of the first translation unit dynamically initialized that includes header <system_error>.

Returns: A reference to an object of a type derived from class error_category.

Remarks: 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 "iostream".

Date: 2010-10-21.18:28:33

[ Post Summit: ]

Agreement that this is wise and essential, text provided works and has been implemented. Seems to be widespread consensus. Move to Tentative Ready.

Date: 2010-10-21.18:28:33

[ San Francisco: ]

Martin: prefers not to create more file-scope static objects, and would like to see get_* functions instead.

[Pre-Summit:]

Beman: The proposed resolution has been reworked to remove the file-scope static objects, per Martin's suggestions. The get_ prefix has been eliminated from the function names as no longer necessary and to conform with standard library naming practice.

Date: 2008-09-14.00:00:00

The static const error_category objects generic_category and system_category in header <system_error> are currently declared:

const error_category& get_generic_category();
const error_category& get_system_category();

static const error_category& generic_category = get_generic_category();
static const error_category& system_category = get_system_category();

This formulation has several problems:

  • Implementation details are exposed, since initialization is specified in the interface. This over-constrains implementations without offsetting user benefits. The form of initialization specified may be less than maximally efficient on some platforms.
  • Use of the objects is more expensive in terms of number of machine level instructions. See Implementation experience below.
  • Depending on the compiler, some cost may be incurred by each translation unit that includes the header, even if the objects are not used. This is a common scenario in user code, since the header is included by other standard library headers. It should be mentioned that at least one compilers is able to optimize this cost away, however.

IO streams uses a somewhat different formulation for iostream_category, but still suffer much the same problems.

The original plan was to eliminate these problems by applying the C++0x constexpr feature. See LWG issue 832. However, that approach turned out to be unimplementable, since it would require a constexpr object of a class with virtual functions, and that is not allowed by the core language.

The proposed resolution was developed as an alternative. It mitigates the above problems by removing initialization from the visible interface, allowing implementations flexibility.

Implementation experience:

Prototype implementations of the current WP interface and proposed resolution interface were tested with recent Codegear, GCC, Intel, and Microsoft compilers on Windows. The code generated by the Microsoft compiler was studied at length; the WP and proposal versions generated very similar code. For both versions the compiler did make use of static initialization; apparently the compiler applied an implicit constexpr where useful, even in cases where constexpr would not be permitted by the language!

Acknowledgements:

Martin Sebor, Chris Kohlhoff, and John Lakos provided useful ideas and comments on initialization issues.

History
Date User Action Args
2011-08-23 20:07:26adminsetstatus: wp -> c++11
2010-10-21 18:28:33adminsetmessages: + msg4234
2010-10-21 18:28:33adminsetmessages: + msg4233
2010-10-21 18:28:33adminsetmessages: + msg4232
2008-09-14 00:00:00admincreate