Freestanding Proposal

Change history

R3 -> R4

default_delete

unique_ptr

_Exit

shuffle_order_engine

knuth_b

R2 -> R3

identity

<contract>

<concepts>

shift_left

shift_right

mbstate_t

wint_t

char_traits

R1 -> R2

atoi

isspace

visit

bad_variant_access

bitset

<version>

unique_ptr

make_unique

default_delete

<span>

days

weeks

months

years

<csetjmp>

R0 -> R1

static_assert

unique_ptr

unique_resource

scope_exit

<random>

<compare>

<chrono>

<optional>

<variant>

Abstract

Introduction

The current definition of the freestanding implementation is not very useful. Here is the current high level definition from [intro.compliance]:

7 Two kinds of implementations are defined: a hosted implementation and a freestanding implementation. For a hosted implementation, this document defines the set of available libraries. A freestanding implementation is one in which execution may take place without the benefit of an operating system, and has animplementation-defined set of libraries that includes certain language-support libraries ([compliance]).

The main people served by the current freestanding definition are people writing their own hosted C++ standard library to sit atop the compiler author's freestanding implementation (i.e. the STLport use case). The freestanding portions contain all the functions and types known to the compiler that can't easily be authored in a cross-compiler manner.

The current set of freestanding libraries provides too little to kernel, micro-controller, and GPU programmers. Why should a systems programmer need to rewrite std::sort() or std::memcpy() ?

I propose we provide the (nearly) maximal subset of the library that does not require an OS or space overhead. In order to continue supporting the "layered" C++ standard library users, we will continue to provide the (nearly) minimal subset of the library needed to support all the language features, even if these features have space overhead. Language features requiring space overhead or OS support will remain intact.

Motivation

Systems programmers want to sort things. They want to use move semantics. They may even want to bundle the arguments of a variadic template function into a std::tuple . These are all reasonable things to do on a system with no operating system and kilobytes of storage. The C++ standard even has reasonable specifications for these operations in the context of a tiny, OS-less system. However, systems programmers must currently rely on either hand-rolled code or implementer extensions in order to get these facilities.

Systems programmers don't have a guide as to what C++ library facilities will work without trying them. The standard says atomic_load will work; memcpy will probably work; but will stable_sort ? Standardizing the subset of implementable C++ that is usable in a freestanding environment would provide clarity here, and help to educate systems programmers.

Current State

There were some presentations at recent CppCons where others made a more full featured C++ work in the Linux and Windows kernels [Quinn2016] [Baker2017]. In both of these cases, C++ was being used in a sandboxed / pseudo-virtualized way. C++ code (with exceptions and RTTI) was being run in the kernel context, but very few calls were made between the C++ code and the operating system kernel. The C++ code was in a guest operating system. This proposal should make it reasonable to have C++ code interact closely with the internals of a host operating system, perhaps in the context of a driver.

The Microsoft Windows kernel and Apple Mac OSX kernel both currently support limited, non-compliant subsets of C++ for driver writers. The Linux kernel does not support C++ officially, though with a fair amount of work on the part of the driver developer, C++ can be made to work. Drivers written in C++ are highly unlikely to be accepted in the upstream Linux source repositories.

IncludeOS [Bratterud2017] is an OS primarily intended for running in VMs, though some bare metal support has been tested. One might expect such a project to use a freestanding implementation as a base, but instead, it starts with a hosted implmentation of C++ and drops support for the impractical parts (threads and filestreams in particular).

Out of libstdc++, libc++, and Microsoft's Visual Studio STL, only libstdc++ has any relevant mention of "freestanding" or "hosted". In practice, users take a hosted implementation of C++ and use it as-is in situations where it was never intended. This means that all the headers tend to be available, but only a few of the headers actually work. Many of the headers that work aren't marked freestanding. Some headers have parts that could work, except they are mixed with other parts that won't work. For example, iterator_traits in <iterator> is fine, but the implementation details of the stream iterators cause build errors with the /kernel flag in Microsoft Visual Studio 2017 15.7.

Scope

The current scope of this proposal is limited to the freestanding standard library available to micro-controller, kernel, and GPU development.

This paper is currently concerned with the divisions of headers and library functions as they were in C++17. "Standard Library Modules" (P0581) discusses how the library will be split up in a post-modules world. This paper may influence the direction of P0581, but this paper won't make any modules recommendations.

I could see the scope increasing to the availability of the standard library on GPUs.

Impact on the standard

The standard will no longer list all of the facilities available to the freestanding implementation, as is currently done in [compliance]. Instead, [compliance] will list all the headers that are required to be present, and the header and class synopses will tag which parts of the headers and classes will be available. This is a large number of small, easy to understand edits, along with the addition of a sub-clause that discusses how the tagging works.

There is precedent for this kind of tagging in other specification documents. The ECMAScript Language Specification has optional support for ECMA-402 (internationalization). The impact of ECMA-402 is called out explicitly in several places. POSIX tags functions as supported in base, XSI, or in one of many option groups.

There were some conversations in the 2017 Albuquerque meeting around adding another class of conforming implementation. I believe that such an action would be a mistake. Maintaining two classifications is difficult enough as is, and freestanding is often neglected. Adding another classification would magnify these problems. I also feel that the freestanding classification should be removed if no action is taken to make it more useful.

Naming alternatives

There was some desire to come up with a new name for "freestanding" in the 2017 Albuquerque meeting. This new name could better express the intended audience of such an implementation. My current recommendation will be to keep the name "freestanding", but I will suggest some alternatives just the same.

backless

barebones

basic

embedded

foundational

freestanding

fundamental

independent

kernel

minimal

OS-free

OS-less

portable

reduced

resource-constrained

skeleton

standalone

stripped

system-free

unsupported

Impact on implementations

C++ standard library headers will likely need to add preprocessor feature toggles to portions of headers that would emit warnings or errors in freestanding mode. The precision and timeliness (compile time vs. link time) of errors remains a quality-of-implementation detail.

A minimal freestanding C11 standard library will not be sufficient to provide the C portions of the C++ standard library. std::char_traits and many of the function specializations in <algorithm> are implemented in terms of non-freestanding C functions. In practice, most C libraries are not minimal freestanding C11 libraries. The optimized versions of the <cstring> and <cwchar> functions will typically be the same for both hosted and freestanding environments.

My expectation is that no new freestanding library will be authored as a result of this paper. Instead hosted libraries will be stripped down through some feature toggle mechanism to become freestanding.

The Microsoft Visual Studio standard library implementation has taken recent steps in version 15.8 (released Aug 14, 2018) to try to better enable uses of the standard library in the kernel. From the Features and Fixes blog post

The header structure of the STL was changed to allow use of a subset of the library in conditions where the user can’t link with msvcp140.dll, such as driver development. [...] The following headers are now considered “core” and don’t inject our runtime dependencies (though we do still assume some form of CRT headers are present): <cstddef>

<cstdlib>

<initializer_list>

<ratio>

<type_traits>

I was able to test the Microsoft Visual Studio 15.8 implementation. The C++14 parts of my additions were able to run in the Windows kernel successfully. I don't have tests for the C++17 and C++20 parts.

I had the following email discussion with Jonathan Wakely, the maintainer of libstdc++, the gcc implementation of the C++ standard library.

From: Ben Craig

If *someone* (possibly me) added the maze of #ifdefs to a branch of libstdc++ to support p0829, would the libstdc++ maintainers be willing to accept and maintain such a thing (assuming it is in the working draft, has tests, high quality, etc)? From: Jonathan Wakely

Yes, definitely. If it's in the WP (and even better, useful to constrained environments) we will support it. GCC is heavily used on bare-metal systems (especially ARM) and if those users can leverage the C++ standard library then we provide more value to them.

From: Ben Craig

[...] If *someone* (possibly me) added the maze of #ifdefs to a branch of libc++ to support p0829, would the libc++ maintainers be willing to accept and maintain such a thing (assuming it is in the working draft, has tests, high quality, etc)? In the next draft of p0829, may I publicly state that libc++ would be willing to add that support? [...] From: Marshall Clow

I haven’t been ignoring you, but rather talking to a bunch of people who use libc++ In general, they are in favor of supporting a freestanding mode for libc++. Some of them, however, have serious concerns about p0829. So, yes, you can put my name on the list, but I suspect you’ll get comments about the specifics.

Design decisions

Even more so than for a hosted implementation; kernel, micro-controller, and GPU programmers do not want to pay for what they don't use. As a consequence, I am not adding features that require global storage, even if that storage is immutable.

Note that the following concerns are not revolving around execution time performance. These are generally concerns about space overhead and correctness.

This proposal doesn't remove problematic features from the language, but it does make it so that the bulk of the freestanding standard library doesn't require those features. Users that disable the problematic features (as is existing practice) will still have portable portions of the standard library at their disposal.

Note that we cannot just take the list of constexpr functions and make those functions the freestanding subset. We also can't do the reverse, and make everything freestanding constexpr or conditionally noexcept . memcpy cannot currently be made constexpr because it must convert from cv void* to unsigned char[] . Several floating point functions could be made constexpr , but would not be permitted in freestanding. constexpr also allows allocations, which freestanding avoids.

We also cannot just take the list of everything that is conditionally noexcept and make those functions freestanding. The "Lakos Rule"[Meredith11] prohibits most standard library functions from being conditionally noexcept , unless they have a wide contract.

Regardless, if a function or class is constexpr or noexcept , and it doesn't involve floating point, then that function or class is a strong candidate to be put into freestanding mode.

In the future, it may make sense to allow all constexpr functions into freestanding, so long as they are used in a constexpr context and not invoked at runtime.

Exceptions

Exceptions either require external jump tables or extra bookkeeping instructions. This consumes program storage space.

In the Itanium ABI, throwing an exception requires a heap allocation. In the Microsoft ABI, re-throwing an exception will consume surprisingly large amounts of stack space (2,100 bytes for a re-throw in 32-bit environments, 9,700 bytes in a 64-bit environment). Program storage space, heap space, and stack space are typically scarce resources in micro-controller development.

In environments with threads, exception handling requires the use of thread-local storage.

RTTI

Thread-local storage

The heap

operator new

Floating point

Many micro-controller systems don't have floating point hardware. Software emulated floating point can drag in large runtimes that are difficult to optimize away.

Most operating systems speed up system calls by not saving and restoring floating point state. That means that kernel uses of floating point operations require extra care to avoid corrupting user state.

Functions requiring global or thread-local storage

Parallel algorithms

<algorithms>

<numeric>

<memory>

Partial class inclusion

Some classes are only partially freestanding. In the Albuquerque 2017 meeting, there was no consensus on allowing or prohibiting this (SF F N A SA 0 9 3 5 1).

In this proposal, I partially include three classes: std::array , std::string_view , and std::optional . If we were designing these classes from scratch with a freestanding environment in mind, they would have the exact same layout and the exact same interface, with the exception of the excluded methods. I think it is highly unlikely that the committee would standardize a std::freestanding_array that was the exact same as std::array , just without the at() method.

I would like to call out std::variant as well. While I do include the entire class, I do exclude the get() function. get() is logically part of the interface. The same general argument I used for std::array , std::string_view , and std::optional holds for std::variant .

Technical Specifications

Complete headers newly required for freestanding implementations

<csetjmp>

<utility>

<tuple>

<ratio>

<compare>

<span>

<contract>

<ranges>

Partial headers newly required for freestanding implementations

<cstdlib>

size_t

div_t

ldiv_t

lldiv_t

NULL

bsearch

qsort

abs(int)

abs(long int)

abs(long long int)

labs

llabs

div

ldiv

lldiv

All the error #defines in <cerrno> , but not errno .

The errc enum from <system_error> .

All of <optional> , except for bad_optional_access and optional::value . The optional value can be accessed through the unchecked observers, operator* and operator-> .

All of <variant> , except for get . The variant value can be accessed through get_if .

All of <bitset> except for operator<<; operator>>; bitset::to_string; the bitset string constructors; and the indexed versions of bitset::set, bitset::reset, and bitset::flip.

Portions of <memory> .

pointer_traits

to_address

align

allocator_arg_t

allocator_arg

uses_allocator

allocator_traits

[specialized.algorithms], except for the ExecutionPolicy overloads

unique_ptr

default_delete

uses_allocator_v

Most of <functional> . Omit the following.

[func.wrap], polymorphic function wrappers (i.e. std::function and friends).

and friends). [func.search.bm], boyer_moore_searcher

[func.search.bmh], boyer_moore_horspool_searcher

<chrono> durations and duration math. Omit clocks, civil time, and streaming functions.

Portions of <charconv> .

to_chars_result

from_chars_result

to_chars (integral)

(integral) from_chars (integral)

The char_traits class from <string> .

Most of <string_view> . These functions will be omitted:

operator<<

basic_string_view::at

basic_string_view::copy

basic_string_view::substr

basic_string_view::compare(size_type pos1, size_type n1, basic_string_view s);

basic_string_view::compare(size_type pos1, size_type n1, basic_string_view s, size_type pos2, size_type n2);

basic_string_view::compare(size_type pos1, size_type n1, const charT* s);

basic_string_view::compare(size_type pos1, size_type n1, const charT* s, size_type n2);

Portions of <cstring> .

memcpy

memmove

strcpy

strncpy

strcat

strncat

memcmp

strcmp

strncmp

memchr

strchr

strcspn

strpbrk

strrchr

strspn

strstr

memset

strlen

<cwchar>

wcscpy

wcsncpy

wmemcpy

wmemmove

wcscat

wcsncat

wcscmp

wcsncmp

wmemcmp

wcschr

wcscspn

wcspbrk

wcsrchr

wcsspn

wcsstr

wcstok

wmemchr

wcslen

wmemset

All of <array> except for array::at .

All of <iterator> except for the stream iterators.

Most of <algorithm> and <numeric> . The ExecutionPolicy overloads will not be included. The following functions will be omitted due to the usage of temporary buffers:

stable_sort

stable_partition

inplace_merge

Portions of <random> . The following portions will be included:

linear_congruential_engine

mersenne_twister_engine

subtract_with_carry_engine

discard_block_engine

independent_bits_engine

[rand.predef], except for knuth_b

uniform_int_distribution

<cmath>

abs(int)

abs(long int)

abs(long long int)

<cinttypes>

imaxabs

imaxdiv

abs(intmax_t)

div(intmax_t, intmax_t)

Notable omissions

errno is not included as it is global state. In addition, errno is best implemented as a thread-local variable.

error_code , error_condition , and error_category all have string in the interface.

Many string functions ( strtol and family) rely on errno .

strtok and rand aren't required to use thread-local storage, but good implementations do. I don't want to encourage bad implementations.

assert is not included as it requires a stderror stream.

_Exit is not included as I do not wish to add more termination functions. I hope to remove most of them in the future. Program termination requires involvement from the operating system / environment.

<cctype> and <cwctype> rely heavily on global locale data.

make_unique is not included, although unique_ptr is included. make_unique has a dependency on heap management functionality, and can throw on heap exhaustion.

seed_seq uses the heap. Users can create their own classes satisfying the seed sequence requirements if they wish to use the Sseq constructors on the engine templates.

shuffle_order_engine doesn't have floating point in its interface, but the algorithm in the standard uses math on the real numbers, which is typically translated into code as floating point. knuth_b is just a convenience typedef on shuffle_order_engine . shuffle_order_engine can be added if an efficient non-floating point implementation of the algorithm is discovered.

Potential removals

<cwchar>

<cwchar>

Insert iterators

back_insert_iterator

front_insert_iterator

insert_iterator

fixed_capacity_vector

visit

visit

variant

variant

bad_variant_access

unique_ptr

unique_ptr

unique_ptr

default_delete

default_delete

delete

default_delete

new

delete

operator new

operator delete

default_delete

unique_ptr

Partial classes

array

bitset

optional

string_view

variant

array

bitset

string_view

std::string

Potential additions

complex<integer>

complex

complex

complex

Floating point support

<cmath>

errno

errno and string functions like strtol

errno

Feature Test Macros

A freestanding implementation that provides support for this paper shall define the following feature test macro.

Name Value Header __cpp_freestanding_library 201803 <version>

The __cpp_freestanding_library macro is useful for detecting the absence of throwing facilities. A user could conditionally use a hand-rolled implementation in freestanding mode or the standard implementation in hosted mode.

The library feature macros have been partitioned into those that must be present in both freestanding and hosted mode, and those that only need to be present in hosted mode. If the implementation provides more than the minimal freestanding subset, then the implementation shall also provide the corresponding feature test macros.

The pre-existing feature macros were not provided on freestanding / hosted boundaries. As a result, a choice has to be made about feature test macros that contain both freestanding and non-freestanding code (e.g. __cpp_lib_chrono , __cpp_lib_boyer_moore_searcher , and others). This revision includes feature test macros in freestanding if any of the feature is included in freestanding. Users that need to detect the non-freestanding parts will also need to test against __cpp_freestanding_library .

Wording

Wording is based off of an intermediate version of Working Draft, Standard for Programming Language C++, from July 26, 2018.

?.?.?.? Freestanding membership [freestanding.membership] 1 The freestanding implementation has several declarations and macro definitions that shall meet the same requirements as for a hosted implementation unless otherwise specified. In the associated header synopsis for such declarations and macro definitions, the items shall be followed with a comment that ends with freestanding , as in: #define E2BIG see below 2 The freestanding implementation has several headers that shall meet the same requirements as for a hosted implementation unless otherwise specified. The synopsis for these headers shall start with a comment that ends with freestanding , as in: namespace std { Individual declarations and macro definitions in such a header shall not be followed with a comment that ends with freestanding . 3 Some classes and class templates are required to be partially implemented in a freestanding implementation. Such entities are permitted to be fully implemented in a freestanding implementation. In the associated header synopsis for such declarations, the declarations shall be followed with a comment that ends with freestanding, partial , as in: template<class T> class optional; Some member functions in partially implemented entities are not required to be present in a freestanding implementation. In the associated class or class template synopsis for such member functions, the declarations shall be followed by a comment that ends with freestanding, omit , as in: constexpr const T& value() const&; All declarations in the partially implemented class or class template that are not followed by a freestanding, omit comment shall meet the same requirements as for a hosted implementation unless otherwise specified. 4 Deduction guides for class templates that are implemented (partially or fully) in a freestanding implementation shall be implemented in a freestanding implementation. The containing namespace for each non-namespace declaration that is implemented (partially or fully) in a freestanding implementation shall be implemented in a freestanding implementation.



Subclause Header(s) [support.types] Types <cstddef> [support.limits] Implementation properties <cfloat> <limits> <climits> <version> [cstdint] Integer types <cstdint> [support.start.term] Start and termination <cstdlib> [support.dynamic] Dynamic memory management <new> [support.rtti] Type identification <typeinfo> [support.exception] Exception handling <exception> [support.initlist] Initializer lists <initializer_­list> [support.runtime] Other runtime support <cstdarg> [concepts] Concepts library <concepts> [meta] Type traits <type_­traits> [bit] Bit manipulation <bit> [atomics] Atomics <atomic> Table 22 - C++ headers for freestanding implementations



<algorithm> <cmath> <exception> <ratio> <array> <compare> <functional> <span> <atomic> <concepts> <initializer_list> <string> <bit> <contract> <iterator> <string_view> <bitset> <csetjmp> <limits> <system_error> <cerrno> <cstdarg> <memory> <tuple> <cfloat> <cstddef> <new> <type_traits> <charconv> <cstdint> <numeric> <typeinfo> <chrono> <cstdlib> <optional> <utility> <cinttypes> <cstring> <random> <variant> <climits> <cwchar> <ranges> <version> Table 21 - C++ headers for freestanding implementations

The supplied version of the header <cstdlib> shall declare at least the functions abort , atexit , at_­quick_­exit , exit , and quick_­exit [support.start.term]. The other headers listed in this table shall meet the same requirements as for a hosted implementation. The supplied versions of the header <version> shall meet the requirements specified in [support.limits.general]. The other headers listed in this table shall meet the requirements for a freestanding implementation, as specified in the respective header synopsis.

[cstddef.syn]

[limits.syn]

[climits.syn]

[cfloat.syn]

[cstdint.syn]

[climits.syn]

[cstdint.syn]

[new.syn]

[typeinfo.syn]

[exception.syn]

[initializer_list.syn]

[compare.syn]

[cstdarg.syn]

[csetjmp.syn]

[concepts.syn]

[utility.syn]

[tuple.syn]

[meta.type.synop]

[ratio.syn]

[span.syn]

[ranges.syn]

[bit.syn]

[atomics.syn]

??? Header <cstdlib> synopsis [cstdlib.syn] namespace std { using size_t = see below ; using div_t = see below ; using ldiv_t = see below ; using lldiv_t = see below ; } #define NULL see below #define EXIT_FAILURE see below #define EXIT_SUCCESS see below #define RAND_MAX see below #define MB_CUR_MAX see below namespace std { extern "C" using c-atexit-handler = void(); extern "C++" using atexit-handler = void(); extern "C" using c-compare-pred = int(const void*, const void*); extern "C++" using compare-pred = int(const void*, const void*); [[noreturn]] void abort() noexcept; int atexit( c-atexit-handler * func) noexcept; int atexit( atexit-handler * func) noexcept; int at_quick_exit( c-atexit-handler * func) noexcept; int at_quick_exit( atexit-handler * func) noexcept; [[noreturn]] void exit(int status); [[noreturn]] void _Exit(int status) noexcept; [[noreturn]] void quick_exit(int status) noexcept; char* getenv (const char* name); int system(const char* string); void* aligned_alloc(size_t alignment, size_t size); void* calloc(size_t nmemb, size_t size); void free(void* ptr); void* malloc(size_t size); void* realloc(void* ptr, size_t size); double atof(const char* nptr); int atoi(const char* nptr); long int atol(const char* nptr); long long int atoll(const char* nptr); double strtod(const char* nptr, char** endptr); float strtof(const char* nptr, char** endptr); long double strtold(const char* nptr, char** endptr); long int strtol(const char* nptr, char** endptr, int base); long long int strtoll(const char* nptr, char** endptr, int base); unsigned long int strtoul(const char* nptr, char** endptr, int base); unsigned long long int strtoull(const char* nptr, char** endptr, int base); int mblen(const char* s, size_t n); int mbtowc(wchar_t* pwc, const char* s, size_t n); int wctomb(char* s, wchar_t wchar); size_t mbstowcs(wchar_t* pwcs, const char* s, size_t n); size_t wcstombs(char* s, const wchar_t* pwcs, size_t n); void* bsearch(const void* key, const void* base, size_t nmemb, size_t size, c-compare-pred * compar); void* bsearch(const void* key, const void* base, size_t nmemb, size_t size, compare-pred * compar); void qsort(void* base, size_t nmemb, size_t size, c-compare-pred * compar); void qsort(void* base, size_t nmemb, size_t size, compare-pred * compar); int rand(); void srand(unsigned int seed); int abs(int j); long int abs(long int j); long long int abs(long long int j); float abs(float j); double abs(double j); long double abs(long double j); long int labs(long int j); long long int llabs(long long int j); div_t div(int numer, int denom); ldiv_t div(long int numer, long int denom); lldiv_t div(long long int numer, long long int denom); ldiv_t ldiv(long int numer, long int denom); lldiv_t lldiv(long long int numer, long long int denom); }

3 The macros in Table 36 are defined after inclusion of the header <version> or one of the corresponding headers specified in the table. Note : Future versions of this International Standard might replace the values of these macros with greater values. -end note] Future versions of this International Standard might replace the values of these macros with greater values. - 3 On freestanding and hosted implementations, the macros in Table ??35?? are defined after inclusion of the header <version> or one of the corresponding headers specified in the table. On hosted implementations, the macros in Table ??36?? are defined after inclusion of the header <version> or one of the corresponding headers specified in the table. The presence of the macros in Table ??36?? is implementation defined on freestanding implementations. Note : Future versions of this International Standard might replace the values of these macros with greater values. -end note] Future versions of this International Standard might replace the values of these macros with greater values. -

??? A freestanding implementation shall define the __cpp_freestanding_library macro with the value 201803L in the <version> header.

Table ??36?? - Freestanding and hosted standard library feature-test macros

__cpp_lib_addressof_constexpr

__cpp_lib_allocator_traits_is_always_equal

__cpp_lib_apply

__cpp_lib_array_constexpr

__cpp_lib_as_const

__cpp_lib_atomic_is_always_lock_free

__cpp_lib_atomic_ref

__cpp_lib_bind_front

__cpp_lib_bit_cast

__cpp_lib_bool_constant

__cpp_lib_boyer_moore_searcher

__cpp_lib_byte

__cpp_lib_char8_t

__cpp_lib_chrono

__cpp_lib_chrono_udls

__cpp_lib_clamp

__cpp_lib_concepts

__cpp_lib_constexpr_misc

__cpp_lib_constexpr_swap_algorithms

__cpp_lib_exchange_function

__cpp_lib_gcd_lcm

__cpp_lib_hardware_interference_size

__cpp_lib_has_unique_object_representations

__cpp_lib_integer_sequence

__cpp_lib_integral_constant_callable

__cpp_lib_invoke

__cpp_lib_is_aggregate

__cpp_lib_is_constant_evaluated

__cpp_lib_is_final

__cpp_lib_is_invocable

__cpp_lib_is_null_pointer

__cpp_lib_is_swappable

__cpp_lib_launder

__cpp_lib_logical_traits

__cpp_lib_make_from_tuple

__cpp_lib_make_reverse_iterator

__cpp_lib_nonmember_container_access

__cpp_lib_not_fn

__cpp_lib_null_iterators

__cpp_lib_optional

__cpp_lib_ranges

__cpp_lib_raw_memory_algorithms

__cpp_lib_result_of_sfinae

__cpp_lib_robust_nonmodifying_seq_ops

__cpp_lib_sample

__cpp_lib_string_view

__cpp_lib_three_way_comparison

__cpp_lib_to_chars

__cpp_lib_transformation_trait_aliases

__cpp_lib_transparent_operators

__cpp_lib_tuple_element_t

__cpp_lib_tuples_by_type

__cpp_lib_type_trait_variable_templates

__cpp_lib_uncaught_exceptions

__cpp_lib_variant

__cpp_lib_void_t

Table ??37?? - Hosted standard library feature-test macros

__cpp_lib_any

__cpp_lib_complex_udls

__cpp_lib_destroying_delete

__cpp_lib_enable_shared_from_this

__cpp_lib_erase_if

__cpp_lib_execution

__cpp_lib_filesystem

__cpp_lib_generic_associative_lookup

__cpp_lib_generic_unordered_lookup

__cpp_lib_hypot

__cpp_lib_incomplete_container_elements

__cpp_lib_list_remove_return_type

__cpp_lib_make_unique

__cpp_lib_map_try_emplace

__cpp_lib_math_special_functions

__cpp_lib_memory_resource

__cpp_lib_node_extract

__cpp_lib_parallel_algorithm

__cpp_lib_quoted_string_io

__cpp_lib_scoped_lock

__cpp_lib_shared_mutex

__cpp_lib_shared_ptr_arrays

__cpp_lib_shared_ptr_weak_type

__cpp_lib_shared_timed_mutex

__cpp_lib_string_udls

__cpp_lib_unordered_map_try_emplace

?.?.? Header <cerrno> synopsis [cerrno.syn] #define errno see below #define E2BIG see below #define EACCES see below #define EADDRINUSE see below #define EADDRNOTAVAIL see below #define EAFNOSUPPORT see below #define EAGAIN see below #define EALREADY see below #define EBADF see below #define EBADMSG see below #define EBUSY see below #define ECANCELED see below #define ECHILD see below #define ECONNABORTED see below #define ECONNREFUSED see below #define ECONNRESET see below #define EDEADLK see below #define EDESTADDRREQ see below #define EDOM see below #define EEXIST see below #define EFAULT see below #define EFBIG see below #define EHOSTUNREACH see below #define EIDRM see below #define EILSEQ see below #define EINPROGRESS see below #define EINTR see below #define EINVAL see below #define EIO see below #define EISCONN see below #define EISDIR see below #define ELOOP see below #define EMFILE see below #define EMLINK see below #define EMSGSIZE see below #define ENAMETOOLONG see below #define ENETDOWN see below #define ENETRESET see below #define ENETUNREACH see below #define ENFILE see below #define ENOBUFS see below #define ENODATA see below #define ENODEV see below #define ENOENT see below #define ENOEXEC see below #define ENOLCK see below #define ENOLINK see below #define ENOMEM see below #define ENOMSG see below #define ENOPROTOOPT see below #define ENOSPC see below #define ENOSR see below #define ENOSTR see below #define ENOSYS see below #define ENOTCONN see below #define ENOTDIR see below #define ENOTEMPTY see below #define ENOTRECOVERABLE see below #define ENOTSOCK see below #define ENOTSUP see below #define ENOTTY see below #define ENXIO see below #define EOPNOTSUPP see below #define EOVERFLOW see below #define EOWNERDEAD see below #define EPERM see below #define EPIPE see below #define EPROTO see below #define EPROTONOSUPPORT see below #define EPROTOTYPE see below #define ERANGE see below #define EROFS see below #define ESPIPE see below #define ESRCH see below #define ETIME see below #define ETIMEDOUT see below #define ETXTBSY see below #define EWOULDBLOCK see below #define EXDEV see below

?.?.? Header <system_­error> synopsis [system_error.syn] namespace std { class error_category; const error_category& generic_category() noexcept; const error_category& system_category() noexcept; class error_code; class error_condition; class system_error; template<class T> struct is_error_code_enum : public false_type {}; template<class T> struct is_error_condition_enum : public false_type {}; enum class errc { address_family_not_supported, address_in_use, address_not_available,

?.?.? Header <optional> synopsis [optional.syn] namespace std { template<class T> class optional; struct nullopt_t{ see below }; inline constexpr nullopt_t nullopt( unspecified ); class bad_optional_access; template<class T, class U> constexpr bool operator==(const optional<T>&, const optional<U>&); template<class T, class U> constexpr bool operator!=(const optional<T>&, const optional<U>&); template<class T, class U> constexpr bool operator<(const optional<T>&, const optional<U>&); template<class T, class U> constexpr bool operator>(const optional<T>&, const optional<U>&); template<class T, class U> constexpr bool operator<=(const optional<T>&, const optional<U>&); template<class T, class U> constexpr bool operator>=(const optional<T>&, const optional<U>&); template<class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept; template<class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept; template<class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept; template<class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept; template<class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept; template<class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept; template<class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept; template<class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept; template<class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept; template<class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept; template<class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept; template<class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept; template<class T, class U> constexpr bool operator==(const optional<T>&, const U&); template<class T, class U> constexpr bool operator==(const T&, const optional<U>&); template<class T, class U> constexpr bool operator!=(const optional<T>&, const U&); template<class T, class U> constexpr bool operator!=(const T&, const optional<U>&); template<class T, class U> constexpr bool operator<(const optional<T>&, const U&); template<class T, class U> constexpr bool operator<(const T&, const optional<U>&); template<class T, class U> constexpr bool operator>(const optional<T>&, const U&); template<class T, class U> constexpr bool operator>(const T&, const optional<U>&); template<class T, class U> constexpr bool operator<=(const optional<T>&, const U&); template<class T, class U> constexpr bool operator<=(const T&, const optional<U>&); template<class T, class U> constexpr bool operator>=(const optional<T>&, const U&); template<class T, class U> constexpr bool operator>=(const T&, const optional<U>&); template<class T> void swap(optional<T>&, optional<T>&) noexcept( see below ); template<class T> constexpr optional< see below > make_optional(T&&); template<class T, class... Args> constexpr optional<T> make_optional(Args&&... args); template<class T, class U, class... Args> constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args); template<class T> struct hash; template<class T> struct hash<optional<T>>; }

constexpr const T* operator->() const; constexpr T* operator->(); constexpr const T& operator*() const&; constexpr T& operator*() &; constexpr T&& operator*() &&; constexpr const T&& operator*() const&&; constexpr explicit operator bool() const noexcept; constexpr bool has_value() const noexcept; constexpr const T& value() const&; constexpr T& value() &; constexpr T&& value() &&; constexpr const T&& value() const&&; template<class U> constexpr T value_or(U&&) const&; template<class U> constexpr T value_or(U&&) &&;

?.?.? Header <variant> synopsis [variant.syn] namespace std { template<class... Types> class variant; template<class T> struct variant_size; template<class T> struct variant_size<const T>; template<class T> struct variant_size<volatile T>; template<class T> struct variant_size<const volatile T>; template<class T> inline constexpr size_t variant_size_v = variant_size<T>::value; template<class... Types> struct variant_size<variant<Types...>>; template<size_t I, class T> struct variant_alternative; template<size_t I, class T> struct variant_alternative<I, const T>; template<size_t I, class T> struct variant_alternative<I, volatile T>; template<size_t I, class T> struct variant_alternative<I, const volatile T>; template<size_t I, class T> using variant_alternative_t = typename variant_alternative<I, T>::type; template<size_t I, class... Types> struct variant_alternative<I, variant<Types...>>; inline constexpr size_t variant_npos = -1; template<class T, class... Types> constexpr bool holds_alternative(const variant<Types...>&) noexcept; template<size_t I, class... Types> constexpr variant_alternative_t<I, variant<Types...>>& get(variant<Types...>&); template<size_t I, class... Types> constexpr variant_alternative_t<I, variant<Types...>>&& get(variant<Types...>&&); template<size_t I, class... Types> constexpr const variant_alternative_t<I, variant<Types...>>& get(const variant<Types...>&); template<size_t I, class... Types> constexpr const variant_alternative_t<I, variant<Types...>>&& get(const variant<Types...>&&); template<class T, class... Types> constexpr T& get(variant<Types...>&); template<class T, class... Types> constexpr T&& get(variant<Types...>&&); template<class T, class... Types> constexpr const T& get(const variant<Types...>&); template<class T, class... Types> constexpr const T&& get(const variant<Types...>&&); template<size_t I, class... Types> constexpr add_pointer_t<variant_alternative_t<I, variant<Types...>>> get_if(variant<Types...>*) noexcept; template<size_t I, class... Types> constexpr add_pointer_t<const variant_alternative_t<I, variant<Types...>>> get_if(const variant<Types...>*) noexcept; template<class T, class... Types> constexpr add_pointer_t<T> get_if(variant<Types...>*) noexcept; template<class T, class... Types> constexpr add_pointer_t<const T> get_if(const variant<Types...>*) noexcept; template<class... Types> constexpr bool operator==(const variant<Types...>&, const variant<Types...>&); template<class... Types> constexpr bool operator!=(const variant<Types...>&, const variant<Types...>&); template<class... Types> constexpr bool operator<(const variant<Types...>&, const variant<Types...>&); template<class... Types> constexpr bool operator>(const variant<Types...>&, const variant<Types...>&); template<class... Types> constexpr bool operator<=(const variant<Types...>&, const variant<Types...>&); template<class... Types> constexpr bool operator>=(const variant<Types...>&, const variant<Types...>&); template<class Visitor, class... Variants> constexpr see below visit(Visitor&&, Variants&&...); template<class R, class Visitor, class... Variants> constexpr R visit(Visitor&&, Variants&&...); struct monostate; constexpr bool operator==(monostate, monostate) noexcept; constexpr bool operator!=(monostate, monostate) noexcept; constexpr bool operator<(monostate, monostate) noexcept; constexpr bool operator>(monostate, monostate) noexcept; constexpr bool operator<=(monostate, monostate) noexcept; constexpr bool operator>=(monostate, monostate) noexcept; template<class... Types> void swap(variant<Types...>&, variant<Types...>&) noexcept( see below ); class bad_variant_access; template<class T> struct hash; template<class... Types> struct hash<variant<Types...>>; template<> struct hash<monostate>; }

?.?.? Header <bitset> synopsis [bitset.syn] #include <string> #include <iosfwd> namespace std { template<size_t N> class bitset; template<size_t N> bitset<N> operator&(const bitset<N>&, const bitset<N>&) noexcept; template<size_t N> bitset<N> operator|(const bitset<N>&, const bitset<N>&) noexcept; template<size_t N> bitset<N> operator^(const bitset<N>&, const bitset<N>&) noexcept; template<class charT, class traits, size_t N> basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, bitset<N>& x); template<class charT, class traits, size_t N> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const bitset<N>& x); }

?.?.? Class template bitset [template.bitset] namespace std { template<size_t N> class bitset { public: class reference { friend class bitset; reference() noexcept; public: reference(const reference&) = default; ~reference(); reference& operator=(bool x) noexcept; reference& operator=(const reference&) noexcept; bool operator~() const noexcept; operator bool() const noexcept; reference& flip() noexcept; }; constexpr bitset() noexcept; constexpr bitset(unsigned long long val) noexcept; template<class charT, class traits, class Allocator> explicit bitset( const basic_string<charT, traits, Allocator>& str, typename basic_string<charT, traits, Allocator>::size_type pos = 0, typename basic_string<charT, traits, Allocator>::size_type n = basic_string<charT, traits, Allocator>::npos, charT zero = charT('0'), charT one = charT('1')); template<class charT> explicit bitset( const charT* str, typename basic_string<charT>::size_type n = basic_string<charT>::npos, charT zero = charT('0'), charT one = charT('1')); bitset<N>& operator&=(const bitset<N>& rhs) noexcept; bitset<N>& operator|=(const bitset<N>& rhs) noexcept; bitset<N>& operator^=(const bitset<N>& rhs) noexcept; bitset<N>& operator<<=(size_t pos) noexcept; bitset<N>& operator>>=(size_t pos) noexcept; bitset<N>& set() noexcept; bitset<N>& set(size_t pos, bool val = true); bitset<N>& reset() noexcept; bitset<N>& reset(size_t pos); bitset<N> operator~() const noexcept; bitset<N>& flip() noexcept; bitset<N>& flip(size_t pos); constexpr bool operator[](size_t pos) const; reference operator[](size_t pos); unsigned long to_ulong() const; unsigned long long to_ullong() const; template<class charT = char, class traits = char_traits<charT>, class Allocator = allocator<charT>> basic_string<charT, traits, Allocator> to_string(charT zero = charT('0'), charT one = charT('1')) const; size_t count() const noexcept; constexpr size_t size() const noexcept; bool operator==(const bitset<N>& rhs) const noexcept; bool operator!=(const bitset<N>& rhs) const noexcept; bool test(size_t pos) const; bool all() const noexcept; bool any() const noexcept; bool none() const noexcept; bitset<N> operator<<(size_t pos) const noexcept; bitset<N> operator>>(size_t pos) const noexcept; }; template<class T> struct hash; template<size_t N> struct hash<bitset<N>>; }

?.?.? Header <memory> synopsis [memory.syn] 1 The header <memory> defines several types and function templates that describe properties of pointers and pointer-like types, manage memory for containers and other template types, destroy objects, and construct multiple objects in uninitialized memory buffers ([pointer.traits]-[specialized.algorithms]). The header also defines the templates unique_­ptr , shared_­ptr , weak_­ptr , and various function templates that operate on objects of these types ([smartptr]). namespace std { template<class Ptr> struct pointer_traits; template<class T> struct pointer_traits<T*>; template<class Ptr> auto to_address(const Ptr& p) noexcept; template<class T> constexpr T* to_address(T* p) noexcept; enum class pointer_safety { relaxed, preferred, strict }; void declare_reachable(void* p); template<class T> T* undeclare_reachable(T* p); void declare_no_pointers(char* p, size_t n); void undeclare_no_pointers(char* p, size_t n); pointer_safety get_pointer_safety() noexcept; void* align(size_t alignment, size_t size, void*& ptr, size_t& space); template<size_t N, class T> [[nodiscard]] constexpr T* assume_aligned(T* ptr); struct allocator_arg_t { explicit allocator_arg_t() = default; }; inline constexpr allocator_arg_t allocator_arg{}; template<class T, class Alloc> struct uses_allocator; template < class T, class Alloc > inline constexpr bool uses_allocator_v = uses_allocator < T, Alloc > : : value; template < class T, class Alloc, class . . . Args > auto uses_allocator_construction_args ( const Alloc & alloc, Args & & . . . args ) - > see below ; template < class T, class Alloc, class Tuple1, class Tuple2 > auto uses_allocator_construction_args ( const Alloc & alloc, piecewise_construct_t, Tuple1 & & x, Tuple2 & & y ) - > see below ; template < class T, class Alloc > auto uses_allocator_construction_args ( const Alloc & alloc ) - > see below ; template < class T, class Alloc, class U, class V > auto uses_allocator_construction_args ( const Alloc & alloc, U & & u, V & & v ) - > see below ; template < class T, class Alloc, class U, class V > auto uses_allocator_construction_args ( const Alloc & alloc, const pair < U,V > & pr ) - > see below ; template < class T, class Alloc, class U, class V > auto uses_allocator_construction_args ( const Alloc & alloc, pair < U,V > & & pr ) - > see below ; template < class T, class Alloc, class . . . Args > T make_obj_using_allocator ( const Alloc & alloc, Args & & . . . args ) ; template < class T, class Alloc, class . . . Args > T * uninitialized_construct_using_allocator ( T * p, const Alloc & alloc, Args & & . . . args ) ; template<class Alloc> struct allocator_traits; template<class T> class allocator; template<class T, class U> bool operator==(const allocator<T>&, const allocator<U>&) noexcept; template<class T, class U> bool operator!=(const allocator<T>&, const allocator<U>&) noexcept; template < class I > concept no-throw-input-iterator = see below ; template < class I > concept no-throw-forward-iterator = see below ; template < class S, class I > concept no-throw-sentinel = see below ; template < class R > concept no-throw-input-range = see below ; template < class R > concept no-throw-forward-range = see below ; template<class T> constexpr T* addressof(T& r) noexcept; template<class T> const T* addressof(const T&&) = delete; template<class ForwardIterator> void uninitialized_default_construct(ForwardIterator first, ForwardIterator last); template<class ExecutionPolicy, class ForwardIterator> void uninitialized_default_construct(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last); template<class ForwardIterator, class Size> ForwardIterator uninitialized_default_construct_n(ForwardIterator first, Size n); template<class ExecutionPolicy, class ForwardIterator, class Size> ForwardIterator uninitialized_default_construct_n(ExecutionPolicy&& exec, ForwardIterator first, Size n); namespace ranges { template < no-throw-forward-iterator I, no-throw-sentinel < I > S > requires DefaultConstructible < iter_value_t < I > > I uninitialized_default_construct ( I first, S last ) ; template < no-throw-forward-range R > requires DefaultConstructible < iter_value_t < iterator_t < R > > > safe_iterator_t < R > uninitialized_default_construct ( R & & r ) ; template < no-throw-forward-iterator I > requires DefaultConstructible < iter_value_t < I > > I uninitialized_default_construct_n ( I first, iter_difference_t < I > n ) ; } template<class ForwardIterator> void uninitialized_value_construct(ForwardIterator first, ForwardIterator last); template<class ExecutionPolicy, class ForwardIterator> void uninitialized_value_construct(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last); template<class ForwardIterator, class Size> ForwardIterator uninitialized_value_construct_n(ForwardIterator first, Size n); template<class ExecutionPolicy, class ForwardIterator, class Size> ForwardIterator uninitialized_value_construct_n(ExecutionPolicy&& exec, ForwardIterator first, Size n); namespace ranges { template < no-throw-forward-iterator I, no-throw-sentinel < I > S > requires DefaultConstructible < iter_value_t < I > > I uninitialized_value_construct ( I first, S last ) ; template < no-throw-forward-range R > requires DefaultConstructible < iter_value_t < iterator_t < R > > > safe_iterator_t < R > uninitialized_value_construct ( R & & r ) ; template < no-throw-forward-iterator I > requires DefaultConstructible < iter_value_t < I > > I uninitialized_value_construct_n ( I first, iter_difference_t < I > n ) ; } template<class InputIterator, class ForwardIterator> ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result); template<class ExecutionPolicy, class InputIterator, class ForwardIterator> ForwardIterator uninitialized_copy(ExecutionPolicy&& exec, InputIterator first, InputIterator last, ForwardIterator result); template<class InputIterator, class Size, class ForwardIterator> ForwardIterator uninitialized_copy_n(InputIterator first, Size n, ForwardIterator result); template<class ExecutionPolicy, class InputIterator, class Size, class ForwardIterator> ForwardIterator uninitialized_copy_n(ExecutionPolicy&& exec, InputIterator first, Size n, ForwardIterator result); namespace ranges { template < class I, class O > using uninitialized_copy_result = copy_result < I, O > ; template < InputIterator I, Sentinel < I > S1, no-throw-forward-iterator O, no-throw-sentinel < O > S2 > requires Constructible < iter_value_t < O > , iter_reference_t < I > > uninitialized_copy_result < I, O > uninitialized_copy ( I ifirst, S1 ilast, O ofirst, S2 olast ) ; template < InputRange IR, no-throw-forward-range OR > requires Constructible < iter_value_t < iterator_t < OR > > , iter_reference_t < iterator_t < IR > > > uninitialized_copy_result < safe_iterator_t < IR > , safe_iterator_t < OR > > uninitialized_copy ( IR & & input_range, OR & & output_range ) ; template < class I, class O > using uninitialized_copy_n_result = uninitialized_copy_result < I, O > ; template < InputIterator I, no-throw-forward-iterator O, no-throw-sentinel < O > S > requires Constructible < iter_value_t < O > , iter_reference_t < I > > uninitialized_copy_n_result < I, O > uninitialized_copy_n ( I ifirst, iter_difference_t < I > n, O ofirst, S olast ) ; } template<class InputIterator, class ForwardIterator> ForwardIterator uninitialized_move(InputIterator first, InputIterator last, ForwardIterator result); template<class ExecutionPolicy, class InputIterator, class ForwardIterator> ForwardIterator uninitialized_move(ExecutionPolicy&& exec, InputIterator first, InputIterator last, ForwardIterator result); template<class InputIterator, class Size, class ForwardIterator> pair<InputIterator, ForwardIterator> uninitialized_move_n(InputIterator first, Size n, ForwardIterator result); template<class ExecutionPolicy, class InputIterator, class Size, class ForwardIterator> pair<InputIterator, ForwardIterator> uninitialized_move_n(ExecutionPolicy&& exec, InputIterator first, Size n, ForwardIterator result); namespace ranges { template < class I, class O > using uninitialized_move_result = uninitialized_copy_result < I, O > ; template < InputIterator I, Sentinel < I > S1, no-throw-forward-iterator O, no-throw-sentinel < O > S2 > requires Constructible < iter_value_t < O > , iter_rvalue_reference_t < I > > uninitialized_move_result < I, O > uninitialized_move ( I ifirst, S1 ilast, O ofirst, S2 olast ) ; template < InputRange IR, no-throw-forward-range OR > requires Constructible < iter_value_t < iterator_t < OR > > , iter_rvalue_reference_t < iterator_t < IR > > > uninitialized_move_result < safe_iterator_t < IR > , safe_iterator_t < OR > > uninitialized_move ( IR & & input_range, OR & & output_range ) ; template < class I, class O > using uninitialized_move_n_result = uninitialized_copy_result < I, O > ; template < InputIterator I, no-throw-forward-iterator O, no-throw-sentinel < O > S > requires Constructible < iter_value_t < O > , iter_rvalue_reference_t < I > > uninitialized_move_n_result < I, O > uninitialized_move_n ( I ifirst, iter_difference_t < I > n, O ofirst, S olast ) ; } template<class ForwardIterator, class T> void uninitialized_fill(ForwardIterator first, ForwardIterator last, const T& x); template<class ExecutionPolicy, class ForwardIterator, class T> void uninitialized_fill(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& x); template<class ForwardIterator, class Size, class T> ForwardIterator uninitialized_fill_n(ForwardIterator first, Size n, const T& x); template<class ExecutionPolicy, class ForwardIterator, class Size, class T> ForwardIterator uninitialized_fill_n(ExecutionPolicy&& exec, ForwardIterator first, Size n, const T& x); namespace ranges { template < no-throw-forward-iterator I, no-throw-sentinel < I > S, class T > requires Constructible < iter_value_t < I > , const T & > I uninitialized_fill ( I first, S last, const T & x ) ; template < no-throw-forward-range R, class T > requires Constructible < iter_value_t < iterator_t < R > > , const T & > safe_iterator_t < R > uninitialized_fill ( R & & r, const T & x ) ; template < no-throw-forward-iterator I, class T > requires Constructible < iter_value_t < I > , const T & > I uninitialized_fill_n ( I first, iter_difference_t < I > n, const T & x ) ; } template<class T> void destroy_at(T* location); template<class ForwardIterator> void destroy(ForwardIterator first, ForwardIterator last); template<class ExecutionPolicy, class ForwardIterator> void destroy(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last); template<class ForwardIterator, class Size> ForwardIterator destroy_n(ForwardIterator first, Size n); template<class ExecutionPolicy, class ForwardIterator, class Size> ForwardIterator destroy_n(ExecutionPolicy&& exec, ForwardIterator first, Size n); namespace ranges { template < Destructible T > void destroy_at ( T * location ) noexcept ; template < no-throw-input-iterator I, no-throw-sentinel < I > S > requires Destructible < iter_value_t < I > > I destroy ( I first, S last ) noexcept ; template < no-throw-input-range R > requires Destructible < iter_value_t < iterator_t < R > > safe_iterator_t < R > destroy ( R & & r ) noexcept ; template < no-throw-input-iterator I > requires Destructible < iter_value_t < I > > I destroy_n ( I first, iter_difference_t < I > n ) noexcept ; } template<class T> struct default_delete; template<class T> struct default_delete<T[]>; template<class T, class D = default_delete<T>> class unique_ptr; template<class T, class D> class unique_ptr<T[], D>; template < class T, class . . . Args > unique_ptr < T > make_unique ( Args & & . . . args ) ; template < class T > unique_ptr < T > make_unique ( size_t n ) ; template < class T, class . . . Args > unspecified make_unique ( Args & & . . . ) = delete ; template < class T > unique_ptr < T > make_unique_default_init ( ) ; template < class T > unique_ptr < T > make_unique_default_init ( size_t n ) ; template < class T, class . . . Args > unspecified make_unique_default_init ( Args & & . . . ) = delete ; template<class T, class D> void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) noexcept; template<class T1, class D1, class T2, class D2> bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template<class T1, class D1, class T2, class D2> bool operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template<class T1, class D1, class T2, class D2> bool operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template<class T1, class D1, class T2, class D2> bool operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template<class T1, class D1, class T2, class D2> bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template<class T1, class D1, class T2, class D2> bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template<class T, class D> bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept; template<class T, class D> bool operator==(nullptr_t, const unique_ptr<T, D>& y) noexcept; template<class T, class D> bool operator!=(const unique_ptr<T, D>& x, nullptr_t) noexcept; template<class T, class D> bool operator!=(nullptr_t, const unique_ptr<T, D>& y) noexcept; template<class T, class D> bool operator<(const unique_ptr<T, D>& x, nullptr_t); template<class T, class D> bool operator<(nullptr_t, const unique_ptr<T, D>& y); template<class T, class D> bool operator>(const unique_ptr<T, D>& x, nullptr_t); template<class T, class D> bool operator>(nullptr_t, const unique_ptr<T, D>& y); template<class T, class D> bool operator<=(const unique_ptr<T, D>& x, nullptr_t); template<class T, class D> bool operator<=(nullptr_t, const unique_ptr<T, D>& y); template<class T, class D> bool operator>=(const unique_ptr<T, D>& x, nullptr_t); template<class T, class D> bool operator>=(nullptr_t, const unique_ptr<T, D>& y); template<class E, class T, class Y, class D> basic_ostream<E, T>& operator<<(basic_ostream<E, T>& os, const unique_ptr<Y, D>& p); class bad_weak_ptr; template<class T> class shared_ptr; template < class T, class . . . Args > shared_ptr < T > make_shared ( Args & & . . . args ) ; template < class T, class A, class . . . Args > shared_ptr < T > allocate_shared ( const A & a, Args & & . . . args ) ; template < class T > shared_ptr < T > make_shared ( size_t N ) ; template < class T, class A > shared_ptr < T > allocate_shared ( const A & a, size_t N ) ; template < class T > shared_ptr < T > make_shared ( ) ; template < class T, class A > shared_ptr < T > allocate_shared ( const A & a ) ; template < class T > shared_ptr < T > make_shared ( size_t N, const remove_extent_t < T > & u ) ; template < class T, class A > shared_ptr < T > allocate_shared ( const A & a, size_t N, const remove_extent_t < T > & u ) ; template < class T > shared_ptr < T > make_shared ( const remove_extent_t < T > & u ) ; template < class T, class A > shared_ptr < T > allocate_shared ( const A & a, const remove_extent_t < T > & u ) ; template < class T > shared_ptr < T > make_shared_default_init ( ) ; template < class T, class A > shared_ptr < T > allocate_shared_default_init ( const A & a ) ; template < class T > shared_ptr < T > make_shared_default_init ( size_t N ) ; template < class T, class A > shared_ptr < T > allocate_shared_default_init ( const A & a, size_t N ) ; template<class T, class U> bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template<class T, class U> bool operator!=(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template<class T, class U> bool operator<(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template<class T, class U> bool operator>(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template<class T, class U> bool operator<=(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template<class T, class U> bool operator>=(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template<class T> bool operator==(const shared_ptr<T>& x, nullptr_t) noexcept; template<class T> bool operator==(nullptr_t, const shared_ptr<T>& y) noexcept; template<class T> bool operator!=(const shared_ptr<T>& x, nullptr_t) noexcept; template<class T> bool operator!=(nullptr_t, const shared_ptr<T>& y) noexcept; template<class T> bool operator<(const shared_ptr<T>& x, nullptr_t) noexcept; template<class T> bool operator<(nullptr_t, const shared_ptr<T>& y) noexcept; template<class T> bool operator<=(const shared_ptr<T>& x, nullptr_t) noexcept; template<class T> bool operator<=(nullptr_t, const shared_ptr<T>& y) noexcept; template<class T> bool operator>(const shared_ptr<T>& x, nullptr_t) noexcept; template<class T> bool operator>(nullptr_t, const shared_ptr<T>& y) noexcept; template<class T> bool operator>=(const shared_ptr<T>& x, nullptr_t) noexcept; template<class T> bool operator>=(nullptr_t, const shared_ptr<T>& y) noexcept; template<class T> void swap(shared_ptr<T>& a, shared_ptr<T>& b) noexcept; template < class T, class U > shared_ptr < T > static_pointer_cast ( const shared_ptr < U > & r ) noexcept ; template < class T, class U > shared_ptr < T > static_pointer_cast ( shared_ptr < U > & & r ) noexcept ; template < class T, class U > shared_ptr < T > dynamic_pointer_cast ( const shared_ptr < U > & r ) noexcept ; template < class T, class U > shared_ptr < T > dynamic_pointer_cast ( shared_ptr < U > & & r ) noexcept ; template < class T, class U > shared_ptr < T > const_pointer_cast ( const shared_ptr < U > & r ) noexcept ; template < class T, class U > shared_ptr < T > const_pointer_cast ( shared_ptr < U > & & r ) noexcept ; template < class T, class U > shared_ptr < T > reinterpret_pointer_cast ( const shared_ptr < U > & r ) noexcept ; template < class T, class U > shared_ptr < T > reinterpret_pointer_cast ( shared_ptr < U > & & r ) noexcept ; template<class D, class T> D* get_deleter(const shared_ptr<T>& p) noexcept; template<class E, class T, class Y> basic_ostream<E, T>& operator<<(basic_ostream<E, T>& os, const shared_ptr<Y>& p); template<class T> class weak_ptr; template<class T> void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept; template<class T = void> struct owner_less; template<class T> class enable_shared_from_this; template<class T> struct hash; template<class T, class D> struct hash<unique_ptr<T, D>>; template<class T> struct hash<shared_ptr<T>>; template<class T> struct atomic<shared_ptr<T>>; template<class T> struct atomic<weak_ptr<T>>; }

?.?.? Header <functional> synopsis [functional.syn] namespace std { template<class F, class... Args> invoke_result_t<F, Args...> invoke(F&& f, Args&&... args) noexcept(is_nothrow_invocable_v<F, Args...>); template<class T> class reference_wrapper; template<class T> reference_wrapper<T> ref(T&) noexcept; template<class T> reference_wrapper<const T> cref(const T&) noexcept; template<class T> void ref(const T&&) = delete; template<class T> void cref(const T&&) = delete; template<class T> reference_wrapper<T> ref(reference_wrapper<T>) noexcept; template<class T> reference_wrapper<const T> cref(reference_wrapper<T>) noexcept; template < class T > struct unwrap_reference; template < class T > struct unwrap_ref_decay : unwrap_reference < decay_t < T > > { } ; template < class T > using unwrap_ref_decay_t = typename unwrap_ref_decay < T > : : type; template<class T = void> struct plus; template<class T = void> struct minus; template<class T = void> struct multiplies; template<class T = void> struct divides; template<class T = void> struct modulus; template<class T = void> struct negate; template<> struct plus<void>; template<> struct minus<void>; template<> struct multiplies<void>; template<> struct divides<void>; template<> struct modulus<void>; template<> struct negate<void>; template<class T = void> struct equal_to; template<class T = void> struct not_equal_to; template<class T = void> struct greater; template<class T = void> struct less; template<class T = void> struct greater_equal; template<class T = void> struct less_equal; template<> struct equal_to<void>; template<> struct not_equal_to<void>; template<> struct greater<void>; template<> struct less<void>; template<> struct greater_equal<void>; template<> struct less_equal<void>; template<class T = void> struct logical_and; template<class T = void> struct logical_or; template<class T = void> struct logical_not; template<> struct logical_and<void>; template<> struct logical_or<void>; template<> struct logical_not<void>; template<class T = void> struct bit_and; template<class T = void> struct bit_or; template<class T = void> struct bit_xor; template<class T = void> struct bit_not; template<> struct bit_and<void>; template<> struct bit_or<void>; template<> struct bit_xor<void>; template<> struct bit_not<void>; struct identity; template<class F> unspecified not_fn(F&& f); template < class F, class . . . Args > unspecified bind_front ( F & & , Args & & . . . ) ; template<class T> struct is_bind_expression; template<class T> struct is_placeholder; template<class F, class... BoundArgs> unspecified bind(F&&, BoundArgs&&...); template<class R, class F, class... BoundArgs> unspecified bind(F&&, BoundArgs&&...); namespace placeholders { see below _1; see below _2; . . . see below _ M ; } template<class R, class T> unspecified mem_fn(R T::*) noexcept; class bad_function_call; template<class> class function; template<class R, class... ArgTypes> class function<R(ArgTypes...)>; template<class R, class... ArgTypes> void swap(function<R(ArgTypes...)>&, function<R(ArgTypes...)>&) noexcept; template<class R, class... ArgTypes> bool operator==(const function<R(ArgTypes...)>&, nullptr_t) noexcept; template<class R, class... ArgTypes> bool operator==(nullptr_t, const function<R(ArgTypes...)>&) noexcept; template<class R, class... ArgTypes> bool operator!=(const function<R(ArgTypes...)>&, nullptr_t) noexcept; template<class R, class... ArgTypes> bool operator!=(nullptr_t, const function<R(ArgTypes...)>&) noexcept; template<class ForwardIterator, class BinaryPredicate = equal_to<>> class default_searcher; template<class RandomAccessIterator, class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>, class BinaryPredicate = equal_to<>> class boyer_moore_searcher; template<class RandomAccessIterator, class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>, class BinaryPredicate = equal_to<>> class boyer_moore_horspool_searcher; template<class T> struct hash; template<class T> inline constexpr bool is_bind_expression_v = is_bind_expression<T>::value; template<class T> inline constexpr int is_placeholder_v = is_placeholder<T>::value; namespace ranges { template < class T = void > requires see below struct equal_to; template < class T = void > requires see below struct not_equal_to; template < class T = void > requires see below struct greater; template < class T = void > requires see below struct less; template < class T = void > requires see below struct greater_equal; template < class T = void > requires see below struct less_equal; template < > struct equal_to < void > ; template < > struct not_equal_to < void > ; template < > struct greater < void > ; template < > struct less < void > ; template < > struct greater_equal < void > ; template < > struct less_equal < void > ; } }

?.?.? Header <charconv> synopsis [charconv.syn] namespace std { enum class chars_­format { scientific = unspecified , fixed = unspecified , hex = unspecified , general = fixed | scientific }; struct to_­chars_­result { char* ptr ; errc ec ; }; to_chars_result to_chars(char* first, char* last, see below value, int base = 10); to_chars_result to_chars(char* first, char* last, float value); to_chars_result to_chars(char* first, char* last, double value); to_chars_result to_chars(char* first, char* last, long double value); to_chars_result to_chars(char* first, char* last, float value, chars_format fmt); to_chars_result to_chars(char* first, char* last, double value, chars_format fmt); to_chars_result to_chars(char* first, char* last, long double value, chars_format fmt); to_chars_result to_chars(char* first, char* last, float value, chars_format fmt, int precision); to_chars_result to_chars(char* first, char* last, double value, chars_format fmt, int precision); to_chars_result to_chars(char* first, char* last, long double value, chars_format fmt, int precision); struct from_­chars_­result { const char* ptr ; errc ec ; }; from_chars_result from_chars(const char* first, const char* last, see below & value, int base = 10); from_chars_result from_chars(const char* first, const char* last, float& value, chars_format fmt = chars_format::general); from_chars_result from_chars(const char* first, const char* last, double& value, chars_format fmt = chars_format::general); from_chars_result from_chars(const char* first, const char* last, long double& value, chars_format fmt = chars_format::general); }

?.?.? Header <string> synopsis [string.syn] #include <initializer_list> namespace std { template<class charT> struct char_traits; template<> struct char_traits<char>; template<> struct char_traits<char8_t>; template<> struct char_traits<char16_t>; template<> struct char_traits<char32_t>; template<> struct char_traits<wchar_t>;

?.?.? Header <string_­view> synopsis [string.view.synop] namespace std { template<class charT, class traits = char_traits<charT>> class basic_string_view; template<class charT, class traits> constexpr bool operator==(basic_string_view<charT, traits> x, basic_string_view<charT, traits> y) noexcept; template<class charT, class traits> constexpr bool operator!=(basic_string_view<charT, traits> x, basic_string_view<charT, traits> y) noexcept; template<class charT, class traits> constexpr bool operator< (basic_string_view<charT, traits> x, basic_string_view<charT, traits> y) noexcept; template<class charT, class traits> constexpr bool operator> (basic_string_view<charT, traits> x, basic_string_view<charT, traits> y) noexcept; template<class charT, class traits> constexpr bool operator<=(basic_string_view<charT, traits> x, basic_string_view<charT, traits> y) noexcept; template<class charT, class traits> constexpr bool operator>=(basic_string_view<charT, traits> x, basic_string_view<charT, traits> y) noexcept; template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, basic_string_view<charT, traits> str); using string_view = basic_string_view<char>; using u8string_view = basic_string_view<char8_t>; using u16string_view = basic_string_view<char16_t>; using u32string_view = basic_string_view<char32_t>; using wstring_view = basic_string_view<wchar_t>; template<class T> struct hash; template<> struct hash<string_view>; template<> struct hash<u8string_view>; template<> struct hash<u16string_view>; template<> struct hash<u32string_view>; template<> struct hash<wstring_view>; inline namespace literals { inline namespace string_view_literals { constexpr string_view operator""sv(const char* str, size_t len) noexcept; constexpr u8string_view operator""sv(const char8_t* str, size_t len) noexcept; constexpr u16string_view operator""sv(const char16_t* str, size_t len) noexcept; constexpr u32string_view operator""sv(const char32_t* str, size_t len) noexcept; constexpr wstring_view operator""sv(const wchar_t* str, size_t len) noexcept; } } }

constexpr const_reference operator[](size_type pos) const; constexpr const_reference at(size_type pos) const; constexpr const_reference front() const; constexpr const_reference back() const; constexpr const_pointer data() const noexcept; constexpr void remove_prefix(size_type n); constexpr void remove_suffix(size_type n); constexpr void swap(basic_string_view& s) noexcept; constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const; constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const; constexpr int compare(basic_string_view s) const noexcept; constexpr int compare(size_type pos1, size_type n1, basic_string_view s) const; constexpr int compare(size_type pos1, size_type n1, basic_string_view s, size_type pos2, size_type n2) const; constexpr int compare(const charT* s) const; constexpr int compare(size_type pos1, size_type n1, const charT* s) const; constexpr int compare(size_type pos1, size_type n1, const charT* s, size_type n2) const;

?.?.? Header <cstring> synopsis [cstring.syn] namespace std { using size_t = see [support.types.layout] ; void* memcpy(void* s1, const void* s2, size_t n); void* memmove(void* s1, const void* s2, size_t n); char* strcpy(char* s1, const char* s2); char* strncpy(char* s1, const char* s2, size_t n); char* strcat(char* s1, const char* s2); char* strncat(char* s1, const char* s2, size_t n); int memcmp(const void* s1, const void* s2, size_t n); int strcmp(const char* s1, const char* s2); int strcoll(const char* s1, const char* s2); int strncmp(const char* s1, const char* s2, size_t n); size_t strxfrm(char* s1, const char* s2, size_t n); const void* memchr(const void* s, int c, size_t n); void* memchr(void* s, int c, size_t n); const char* strchr(const char* s, int c); char* strchr(char* s, int c); size_t strcspn(const char* s1, const char* s2); const char* strpbrk(const char* s1, const char* s2); char* strpbrk(char* s1, const char* s2); const char* strrchr(const char* s, int c); char* strrchr(char* s, int c); size_t strspn(const char* s1, const char* s2); const char* strstr(const char* s1, const char* s2); char* strstr(char* s1, const char* s2); char* strtok(char* s1, const char* s2); void* memset(void* s, int c, size_t n); char* strerror(int errnum); size_t strlen(const char* s); } #define NULL see [support.types.nullptr]

?.?.? Header <cwchar> synopsis [cwchar.syn] namespace std { using size_t = see [support.types.layout] ; using mbstate_t = see below ; using wint_t = see below ; struct tm; int fwprintf(FILE* stream, const wchar_t* format, ...); int fwscanf(FILE* stream, const wchar_t* format, ...); int swprintf(wchar_t* s, size_t n, const wchar_t* format, ...); int swscanf(const wchar_t* s, const wchar_t* format, ...); int vfwprintf(FILE* stream, const wchar_t* format, va_list arg); int vfwscanf(FILE* stream, const wchar_t* format, va_list arg); int vswprintf(wchar_t* s, size_t n, const wchar_t* format, va_list arg); int vswscanf(const wchar_t* s, const wchar_t* format, va_list arg); int vwprintf(const wchar_t* format, va_list arg); int vwscanf(const wchar_t* format, va_list arg); int wprintf(const wchar_t* format, ...); int wscanf(const wchar_t* format, ...); wint_t fgetwc(FILE* stream); wchar_t* fgetws(wchar_t* s, int n, FILE* stream); wint_t fputwc(wchar_t c, FILE* stream); int fputws(const wchar_t* s, FILE* stream); int fwide(FILE* stream, int mode); wint_t getwc(FILE* stream); wint_t getwchar(); wint_t putwc(wchar_t c, FILE* stream); wint_t putwchar(wchar_t c); wint_t ungetwc(wint_t c, FILE* stream); double wcstod(const wchar_t* nptr, wchar_t** endptr); float wcstof(const wchar_t* nptr, wchar_t** endptr); long double wcstold(const wchar_t* nptr, wchar_t** endptr); long int wcstol(const wchar_t* nptr, wchar_t** endptr, int base); long long int wcstoll(const wchar_t* nptr, wchar_t** endptr, int base); unsigned long int wcstoul(const wchar_t* nptr, wchar_t** endptr, int base); unsigned long long int wcstoull(const wchar_t* nptr, wchar_t** endptr, int base); wchar_t* wcscpy(wchar_t* s1, const wchar_t* s2); wchar_t* wcsncpy(wchar_t* s1, const wchar_t* s2, size_t n); wchar_t* wmemcpy(wchar_t* s1, const wchar_t* s2, size_t n); wchar_t* wmemmove(wchar_t* s1, const wchar_t* s2, size_t n); wchar_t* wcscat(wchar_t* s1, const wchar_t* s2); wchar_t* wcsncat(wchar_t* s1, const wchar_t* s2, size_t n); int wcscmp(const wchar_t* s1, const wchar_t* s2); int wcscoll(const wchar_t* s1, const wchar_t* s2); int wcsncmp(const wchar_t* s1, const wchar_t* s2, size_t n); size_t wcsxfrm(wchar_t* s1, const wchar_t* s2, size_t n); int wmemcmp(const wchar_t* s1, const wchar_t* s2, size_t n); const wchar_t* wcschr(const wchar_t* s, wchar_t c); wchar_t* wcschr(wchar_t* s, wchar_t c); size_t wcscspn(const wchar_t* s1, const wchar_t* s2); const wchar_t* wcspbrk(const wchar_t* s1, const wchar_t* s2); wchar_t* wcspbrk(wchar_t* s1, const wchar_t* s2); const wchar_t* wcsrchr(const wchar_t* s, wchar_t c); wchar_t* wcsrchr(wchar_t* s, wchar_t c); size_t wcsspn(const wchar_t* s1, const wchar_t* s2); const wchar_t* wcsstr(const wchar_t* s1, const wchar_t* s2); wchar_t* wcsstr(wchar_t* s1, const wchar_t* s2); wchar_t* wcstok(wchar_t* s1, const wchar_t* s2, wchar_t** ptr); const wchar_t* wmemchr(const wchar_t* s, wchar_t c, size_t n); wchar_t* wmemchr(wchar_t* s, wchar_t c, size_t n); size_t wcslen(const wchar_t* s); wchar_t* wmemset(wchar_t* s, wchar_t c, size_t n); size_t wcsftime(wchar_t* s, size_t maxsize, const wchar_t* format, const struct tm* timeptr); wint_t btowc(int c); int wctob(wint_t c); int mbsinit(const mbstate_t* ps); size_t mbrlen(const char* s, size_t n, mbstate_t* ps); size_t mbrtowc(wchar_t* pwc, const char* s, size_t n, mbstate_t* ps); size_t wcrtomb(char* s, wchar_t wc, mbstate_t* ps); size_t mbsrtowcs(wchar_t* dst, const char** src, size_t len, mbstate_t* ps); size_t wcsrtombs(char* dst, const wchar_t** src, size_t len, mbstate_t* ps); } #define NULL see [support.types.nullptr] #define WCHAR_MAX see below #define WCHAR_MIN see below #define WEOF see below

?.?.? Header <array> synopsis [array.syn] #include <initializer_list> namespace std { template<class T, size_t N> struct array; template<class T, size_t N> constexpr bool operator==(const array<T, N>& x, const array<T, N>& y); template<class T, size_t N> constexpr bool operator!=(const array<T, N>& x, const array<T, N>& y); template<class T, size_t N> constexpr bool operator< (const array<T, N>& x, const array<T, N>& y); template<class T, size_t N> constexpr bool operator> (const array<T, N>& x, const array<T, N>& y); template<class T, size_t N> constexpr bool operator<=(const array<T, N>& x, const array<T, N>& y); template<class T, size_t N> constexpr bool operator>=(const array<T, N>& x, const array<T, N>& y); template<class T, size_t N> constexpr void swap(array<T, N>& x, array<T, N>& y) noexcept(noexcept(x.swap(y))); template<class T> class tuple_size; template<size_t I, class T> class tuple_element; template<class T, size_t N> struct tuple_size<array<T, N>>; template<size_t I, class T, size_t N> struct tuple_element<I, array<T, N>>; template<size_t I, class T, size_t N> constexpr T& get(array<T, N>&) noexcept; template<size_t I, class T, size_t N> constexpr T&& get(array<T, N>&&) noexcept; template<size_t I, class T, size_t N> constexpr const T& get(const array<T, N>&) noexcept; template<size_t I, class T, size_t N> constexpr const T&& get(const array<T, N>&&) noexcept; }

constexpr reference operator[](size_type n); constexpr const_reference operator[](size_type n) const; constexpr reference at(size_type n); constexpr const_reference at(size_type n) const; constexpr reference front(); constexpr const_reference front() const; constexpr reference back(); constexpr const_reference back() const;

istream_iterator

ostream_iterator

istreambuf_iterator

ostreambuf_iterator

for_each_result

mismatch_result

copy_result

copy_n_result

copy_if_result

copy_backward_result

move_result

move_backward_result

swap_ranges_result

unary_transform_result

binary_transform_result

replace_copy_result

replace_copy_if_result

remove_copy_result

remove_copy_if_result

unique_copy_result

reverse_copy_result

rotate_copy_result

partition_copy_result

merge_result

set_union_result

set_intersection_result

set_difference_result

set_symmetric_difference_result

minmax_result

ranges

all_of

any_of

none_of

for_each

for_each_n

find

find_if

find_if_not

find_end

find_first_of

adjacent_find

count

count_if

mismatch

equal

is_permutation

search

search_n

copy

copy_n

copy_if

copy_backward

move

move_backward

swap_ranges

iter_swap

transform

replace

replace_if

replace_copy

replace_copy_if

fill

fill_n

generate

generate_n

remove

remove_if

remove_copy

remove_copy_if

unique

unique_copy

reverse

reverse_copy

rotate

rotate_copy

sample

shuffle

shift_left

shift_right

sort

partial_sort

partial_sort_copy

is_sorted

is_sorted_until

nth_element

lower_bound

upper_bound

equal_range

binary_search

is_partitioned

partition

partition_copy

partition_point

merge

includes

set_union

set_intersection

set_difference

set_symmetric_difference

push_heap

pop_heap

make_heap

sort_heap

is_heap

is_heap_until

min

max

minmax

min_element

max_element

minmax_element

clamp

lexicographical_compare

compare_3way

lexicographical_compare_3way

next_permutation

prev_permutation

stable_sort

stable_partition

inplace_merge

accumulate

reduce

inner_product

transform_reduce

partial_sum

exclusive_scan

inclusive_scan

transform_exclusive_scan

transform_inclusive_scan

adjacent_difference

iota

gcd

lcm

?.?.? Header <random> synopsis [rand.synopsis] #include <initializer_list> namespace std { template<class G> concept UniformRandomBitGenerator = see below ; template<class UIntType, UIntType a, UIntType c, UIntType m> class linear_congruential_engine; template<class UIntType, size_t w, size_t n, size_t m, size_t r, UIntType a, size_t u, UIntType d, size_t s, UIntType b, size_t t, UIntType c, size_t l, UIntType f> class mersenne_twister_engine; template<class UIntType, size_t w, size_t s, size_t r> class subtract_with_carry_engine; template<class Engine, size_t p, size_t r> class discard_block_engine; template<class Engine, size_t w, class UIntType> class independent_bits_engine; template<class Engine, size_t k> class shuffle_order_engine; using minstd_rand0 = see below ; using minstd_rand = see below ; using mt19937 = see below ; using mt19937_64 = see below ; using ranlux24_base = see below ; using ranlux48_base = see below ; using ranlux24 = see below ; using ranlux48 = see below ; using knuth_b = see below ; using default_random_engine = see below ; class random_device; class seed_seq; template<class RealType, size_t bits, class URBG> RealType generate_canonical(URBG& g); template<class IntType = int> class uniform_int_distribution; template<class RealType = double> class uniform_real_distribution;

int abs(int j); long int abs(long int j); long long int abs(long long int j); float abs(float j); double abs(double j); long double abs(long double j);

?.? Header <chrono> synopsis [time.syn] namespace std { namespace chrono { template<class Rep, class Period = ratio<1>> class duration; template<class Clock, class Duration = typename Clock::duration> class time_point; } template<class Rep1, class Period1, class Rep2, class Period2> struct common_type<chrono::duration<Rep1, Period1>, chrono::duration<Rep2, Period2>>; template<class Clock, class Duration1, class Duration2> struct common_type<chrono::time_point<Clock, Duration1>, chrono::time_point<Clock, Duration2>>; namespace chrono { template<class Rep> struct treat_as_floating_point; template<class Rep> struct duration_values; template<class Rep> inline constexpr bool treat_as_floating_point_v = treat_as_floating_point<Rep>::value; template<class T> struct is_clock; template<class T> inline constexpr bool is_clock_v = is_clock<T>::value; template<class Rep1, class Period1, class Rep2, class Period2> constexpr common_type_t<duration<Rep1, Period1>, duration<Rep2, Period2>> operator+(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template<class Rep1, class Period1, class Rep2, class Period2> constexpr common_type_t<duration<Rep1, Period1>, duration<Rep2, Period2>> operator-(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template<class Rep1, class Period, class Rep2> constexpr duration<common_type_t<Rep1, Rep2>, Period> operator*(const duration<Rep1, Period>& d, const Rep2& s); template<class Rep1, class Rep2, class Period> constexpr duration<common_type_t<Rep1, Rep2>, Period> operator*(const Rep1& s, const duration<Rep2, Period>& d); template<class Rep1, class Period, class Rep2> constexpr duration<common_type_t<Rep1, Rep2>, Period> operator/(const duration<Rep1, Period>& d, const Rep2& s); template<class Rep1, class Period1, class Rep2, class Period2> constexpr common_type_t<Rep1, Rep2> operator/(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template<class Rep1, class Period, class Rep2> constexpr duration<common_type_t<Rep1, Rep2>, Period> operator%(const duration<Rep1, Period>& d, const Rep2& s); template<class Rep1, class Period1, class Rep2, class Period2> constexpr common_type_t<duration<Rep1, Period1>, duration<Rep2, Period2>> operator%(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template<class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator==(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template<class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator!=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template<class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator< (const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template<class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator> (const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template<class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator<=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template<class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator>=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template<class ToDuration, class Rep, class Period> constexpr ToDuration duration_cast(const duration<Rep, Period>& d); template<class ToDuration, class Rep, class Period> constexpr ToDuration floor(const duration<Rep, Period>& d); template<class ToDuration, class Rep, class Period> constexpr ToDuration ceil(const duration<Rep, Period>& d); template<class ToDuration, class Rep, class Period> constexpr ToDuration round(const duration<Rep, Period>& d); template<class charT, class traits, class Rep, class Period> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const duration<Rep, Period>& d); template<class charT, class traits, class Rep, class Period> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const duration<Rep, Period>& d); template<class charT, class traits, class Rep, class Period, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, duration<Rep, Period>& d, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr); using nanoseconds = duration<signed integer type of at least 64 bits, nano>; using microseconds = duration<signed integer type of at least 55 bits, micro>; using milliseconds = duration<signed integer type of at least 45 bits, milli>; using seconds = duration<signed integer type of at least 35 bits>; using minutes = duration<signed integer type of at least 29 bits, ratio< 60>>; using hours = duration<signed integer type of at least 23 bits, ratio<3600>>; using days = duration<signed integer type of at least 25 bits, ratio_multiply<ratio<24>, hours::period>>; using weeks = duration<signed integer type of at least 22 bits, ratio_multiply<ratio<7>, days::period>>; using years = duration<signed integer type of at least 17 bits, ratio_multiply<ratio<146097, 400>, days::period>>; using months = duration<signed integer type of at least 20 bits, ratio_divide<years::period, ratio<12>>>; template<class Clock, class Duration1, class Rep2, class Period2> constexpr time_point<Clock, common_type_t<Duration1, duration<Rep2, Period2>>> operator+(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs); template<class Rep1, class Period1, class Clock, class Duration2> constexpr time_point<Clock, common_type_t<duration<Rep1, Period1>, Duration2>> operator+(const duration<Rep1, Period1>& lhs, const time_point<Clock, Duration2>& rhs); template<class Clock, class Duration1, class Rep2, class Period2> constexpr time_point<Clock, common_type_t<Duration1, duration<Rep2, Period2>>> operator-(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs); template<class Clock, class Duration1, class Duration2> constexpr common_type_t<Duration1, Duration2> operator-(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); template<class Clock, class Duration1, class Duration2> constexpr bool operator==(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); template<class Clock, class Duration1, class Duration2> constexpr bool operator!=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); template<class Clock, class Duration1, class Duration2> constexpr bool operator< (const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); template<class Clock, class Duration1, class Duration2> constexpr bool operator> (const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); template<class Clock, class Duration1, class Duration2> constexpr bool operator<=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); template<class Clock, class Duration1, class Duration2> constexpr bool operator>=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); template<class ToDuration, class Clock, class Duration> constexpr time_point<Clock, ToDuration> time_point_cast(const time_point<Clock, Duration>& t); template<class ToDuration, class Clock, class Duration> constexpr time_point<Clock, ToDuration> floor(const time_point<Clock, Duration>& tp); template<class ToDuration, class Clock, class Duration> constexpr time_point<Clock, ToDuration> ceil(const time_point<Clock, Duration>& tp); template<class ToDuration, class Clock, class Duration> constexpr time_point<Clock, ToDuration> round(const time_point<Clock, Duration>& tp); template<class Rep, class Period> constexpr duration<Rep, Period> abs(duration<Rep, Period> d);

inline namespace literals { inline namespace chrono_literals { constexpr chrono::hours operator""h(unsigned long long); constexpr chrono::duration< unspecified , ratio<3600, 1>> operator""h(long double); constexpr chrono::minutes operator""min(unsigned long long); constexpr chrono::duration< unspecified , ratio<60, 1>> operator""min(long double); constexpr chrono::seconds operator""s(unsigned long long); constexpr chrono::duration< unspecified > operator""s(long double); constexpr chrono::milliseconds operator""ms(unsigned long long); constexpr chrono::duration< unspecified , milli> operator""ms(long double); constexpr chrono::microseconds operator""us(unsigned long long); constexpr chrono::duration< unspecified , micro> operator""us(long double); constexpr chrono::nanoseconds operator""ns(unsigned long long); constexpr chrono::duration< unspecified , nano> operator""ns(long double); constexpr chrono::day operator""d(unsigned long long d) noexcept; constexpr chrono::year operator""y(unsigned long long y) noexcept; } } namespace chrono { using namespace literals::chrono_literals; } }

?.?.? Header <cinttypes> synopsis [cinttypes.syn] #include <cstdint> namespace std { using imaxdiv_t = see below ; intmax_t imaxabs(intmax_t j); imaxdiv_t imaxdiv(intmax_t numer, intmax_t denom); intmax_t strtoimax(const char* nptr, char** endptr, int base); uintmax_t strtoumax(const char* nptr, char** endptr, int base); intmax_t wcstoimax(const wchar_t* nptr, wchar_t** endptr, int base); uintmax_t wcstoumax(const wchar_t* nptr, wchar_t** endptr, int base); intmax_t abs(intmax_t); imaxdiv_t div(intmax_t, intmax_t); }

Acknowledgements

Thanks to Brandon Streiff, Joshua Cannon, Phil Hindman, and Irwan Djajadi for reviewing this proposal.

Thanks to Odin Holmes for helping publicize this paper, presenting it in Rapperswil, and providing feedback.

Similar work was done in the C++11 timeframe by Lawrence Crowl and Alberto Ganesh Barbati in N3256.

CppCon talks on getting C++ support in various unusual environments:

[Baker2017] CppCon 2017: Billy Baker "Almost Unlimited Modern C++ in Kernel-Mode Applications"

[Quinn2016] CppCon 2016: Rian Quinn "Making C++ and the STL Work in the Linux / Windows Kernels"

[Bratterud2017] CppCon 2017: Alfred Bratterud "Deconstructing the OS: The devil's In the side effects"

[Meredith11] Conservative use of noexcept in the Library. A. Meredith; J. Lakos. N3279.