17 Library introduction [library]

17.6 Library-wide requirements [requirements]

17.6.5 Conforming implementations [conforming]

17.6.5.1 Overview [conforming.overview]

This section describes the constraints upon, and latitude of, implementations of the C++ standard library.

An implementation's use of headers is discussed in [res.on.headers], its use of macros in [res.on.macro.definitions], global functions in [global.functions], member functions in [member.functions], data race avoidance in [res.on.data.races], access specifiers in [protection.within.classes], class derivation in [derivation], and exceptions in [res.on.exception.handling].

17.6.5.2 Headers [res.on.headers]

A C++ header may include other C++ headers. A C++ header shall provide the declarations and definitions that appear in its synopsis. A C++ header shown in its synopsis as including other C++ headers shall provide the declarations and definitions that appear in the synopses of those other headers.

Certain types and macros are defined in more than one header. Every such entity shall be defined such that any header that defines it may be included after any other header that also defines it ([basic.def.odr]).

The C standard headers ([depr.c.headers]) shall include only their corresponding C++ standard header, as described in [headers].

17.6.5.3 Restrictions on macro definitions [res.on.macro.definitions]

The names and global function signatures described in [contents] are reserved to the implementation.

All object-like macros defined by the C standard library and described in this Clause as expanding to integral constant expressions are also suitable for use in #if preprocessing directives, unless explicitly stated otherwise.

17.6.5.4 Global and non-member functions [global.functions]

It is unspecified whether any global or non-member functions in the C++ standard library are defined as inline ([dcl.fct.spec]).

A call to a global or non-member function signature described in Clauses [language.support] through [thread] and Annex [depr] shall behave as if the implementation declared no additional global or non-member function signatures.187

An implementation shall not declare a global or non-member function signature with additional default arguments.

Unless otherwise specified, global and non-member functions in the standard library shall not use functions from another namespace which are found through argument-dependent name lookup ([basic.lookup.argdep]). [ Note: The phrase “unless otherwise specified” is intended to allow argument-dependent lookup in cases like that of ostream_iterators: Effects:

*out_stream << value;
if (delim != 0)
  *out_stream << delim;
return (*this);

 — end note ]

A valid C++ program always calls the expected library global or non-member function. An implementation may also define additional global or non-member functions that would otherwise not be called by a valid C++ program.

17.6.5.5 Member functions [member.functions]

It is unspecified whether any member functions in the C++ standard library are defined as inline ([dcl.fct.spec]).

An implementation may declare additional non-virtual member function signatures within a class:

  • by adding arguments with default values to a member function signature;188Note: An implementation may not add arguments with default values to virtual, global, or non-member functions. — end note ]

  • by replacing a member function signature with default values by two or more member function signatures with equivalent behavior; and

  • by adding a member function signature for a member function name.

A call to a member function signature described in the C++ standard library behaves as if the implementation declares no additional member function signatures.189

Hence, the address of a member function of a class in the C++ standard library has an unspecified type.

A valid C++ program always calls the expected library member function, or one with equivalent behavior. An implementation may also define additional member functions that would otherwise not be called by a valid C++ program.

17.6.5.6 constexpr functions and constructors [constexpr.functions]

Within any header that provides any non-defining declarations of constexpr functions or constructors an implementation shall provide corresponding definitions.

17.6.5.7 Requirements for stable algorithms [algorithm.stable]

When the requirements for an algorithm state that it is “stable” without further elaboration, it means:

  • For the sort algorithms the relative order of equivalent elements is preserved.

  • For the remove algorithms the relative order of the elements that are not removed is preserved.

  • For the merge algorithms, for equivalent elements in the original two ranges, the elements from the first range precede the elements from the second range.

17.6.5.8 Reentrancy [reentrancy]

Except where explicitly specified in this standard, it is implementation-defined which functions in the Standard C++ library may be recursively reentered.

17.6.5.9 Data race avoidance [res.on.data.races]

This section specifies requirements that implementations shall meet to prevent data races ([intro.multithread]). Every standard library function shall meet each requirement unless otherwise specified. Implementations may prevent data races in cases other than those specified below.

A C++ standard library function shall not directly or indirectly access objects ([intro.multithread]) accessible by threads other than the current thread unless the objects are accessed directly or indirectly via the function's arguments, including this.

A C++ standard library function shall not directly or indirectly modify objects ([intro.multithread]) accessible by threads other than the current thread unless the objects are accessed directly or indirectly via the function's non-const arguments, including this.

Note: This means, for example, that implementations can't use a static object for internal purposes without synchronization because it could cause a data race even in programs that do not explicitly share objects between threads.  — end note ]

A C++ standard library function shall not access objects indirectly accessible via its arguments or via elements of its container arguments except by invoking functions required by its specification on those container elements.

Operations on iterators obtained by calling a standard library container or string member function may access the underlying container, but shall not modify it. [ Note: In particular, container operations that invalidate iterators conflict with operations on iterators associated with that container.  — end note ]

Implementations may share their own internal objects between threads if the objects are not visible to users and are protected against data races.

Unless otherwise specified, C++ standard library functions shall perform all operations solely within the current thread if those operations have effects that are visible ([intro.multithread]) to users.

Note: This allows implementations to parallelize operations if there are no visible side effects.  — end note ]

17.6.5.10 Protection within classes [protection.within.classes]

It is unspecified whether any function signature or class described in Clauses [language.support] through [thread] and Annex [depr] is a friend of another class in the C++ standard library.

17.6.5.11 Derived classes [derivation]

An implementation may derive any class in the C++ standard library from a class with a name reserved to the implementation.

Certain classes defined in the C++ standard library are required to be derived from other classes in the C++ standard library. An implementation may derive such a class directly from the required base or indirectly through a hierarchy of base classes with names reserved to the implementation.

In any case:

  • Every base class described as virtual shall be virtual;

  • Every base class described as non-virtual shall not be virtual;

  • Unless explicitly stated otherwise, types with distinct names shall be distinct types.190

There is an implicit exception to this rule for types that are described as synonyms for basic integral types, such as size_t ([support.types]) and streamoff ([stream.types]).

17.6.5.12 Restrictions on exception handling [res.on.exception.handling]

Any of the functions defined in the C++ standard library can report a failure by throwing an exception of a type described in its Throws: paragraph. An implementation may strengthen the exception-specification for a non-virtual function by adding a non-throwing noexcept-specification.

A function may throw an object of a type not listed in its Throws clause if its type is derived from a type named in the Throws clause and would be caught by an exception handler for the base type.

Functions from the C standard library shall not throw exceptions191 except when such a function calls a program-supplied function that throws an exception.192

Destructor operations defined in the C++ standard library shall not throw exceptions. Every destructor in the C++ standard library shall behave as if it had a non-throwing exception specification. Any other functions defined in the C++ standard library that do not have an exception-specification may throw implementation-defined exceptions unless otherwise specified.193 An implementation may strengthen this implicit exception-specification by adding an explicit one.194

That is, the C library functions can all be treated as if they are marked noexcept. This allows implementations to make performance optimizations based on the absence of exceptions at runtime.

The functions qsort() and bsearch() ([alg.c.library]) meet this condition.

In particular, they can report a failure to allocate storage by throwing an exception of type bad_alloc, or a class derived from bad_alloc ([bad.alloc]). Library implementations should report errors by throwing exceptions of or derived from the standard exception classes ([bad.alloc], [support.exception], [std.exceptions]).

That is, an implementation may provide an explicit exception-specification that defines the subset of “any” exceptions thrown by that function. This implies that the implementation may list implementation-defined types in such an exception-specification.

17.6.5.13 Restrictions on storage of pointers [res.on.pointer.storage]

Objects constructed by the standard library that may hold a user-supplied pointer value or an integer of type std::intptr_t shall store such values in a traceable pointer location ([basic.stc.dynamic.safety]). [ Note: Other libraries are strongly encouraged to do the same, since not doing so may result in accidental use of pointers that are not safely derived. Libraries that store pointers outside the user's address space should make it appear that they are stored and retrieved from a traceable pointer location.  — end note ]

17.6.5.14 Value of error codes [value.error.codes]

Certain functions in the C++ standard library report errors via a std::error_code ([syserr.errcode.overview]) object. That object's category() member shall return 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 ]

17.6.5.15 Moved-from state of library types [lib.types.movedfrom]

Objects of types defined in the C++ standard library may be moved from ([class.copy]). Move operations may be explicitly specified or implicitly generated. Unless otherwise specified, such moved-from objects shall be placed in a valid but unspecified state.