1 Explanation and rationale for the approach

The pace of innovation in the standardization of C++ makes long-term stability of implementations unlikely. Features are added to the language because programmers want to use those features. Features are added to (the working draft of) the standard as the features become well-specified. In many cases a feature is added to an implementation well before or well after the standard officially introducing it is approved.

This process makes it difficult for programmers who want to use a feature to know whether it is available in any given implementation. Implementations rarely leap from one formal revision of the standard directly to the next; the implementation process generally proceeds by smaller steps. As a result, testing for a specific revision of the standard (e.g. by examining the value of the __cplusplus macro) often gives the wrong answer. Implementers generally don’t want to appear to be claiming full conformance to a standard revision until all of its features are implemented. That leaves programmers with no portable way to determine which features are actually available to them.

It is often possible for a program to determine, in a manner specific to a single implementation, what features are supported by that implementation; but the means are often poorly documented and ad hoc, and sometimes complex – especially when the availability of a feature is controlled by an invocation option. To make this determination for a variety of implementations in a single source base is complex and error-prone.

1.1 Status quo before feature-test macros

Here is some code that attempts to determine whether rvalue references are available in the implementation in use:

#ifndef __USE_RVALUE_REFERENCES #if ( __GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 3) || \ _MSC_VER >= 1600 #if __EDG_VERSION__ > 0 #define __USE_RVALUE_REFERENCES ( __EDG_VERSION__ >= 410 ) __EDG_VERSION__ #else #define __USE_RVALUE_REFERENCES 1 #endif #elif __clang__ #define __USE_RVALUE_REFERENCES __has_feature ( cxx_rvalue_references ) __has_featurecxx_rvalue_references #else #define __USE_RVALUE_REFERENCES 0 #endif #endif

First, the GNU and Microsoft version numbers are checked to see if they are high enough. But then a check is made of the EDG version number, since that front end also has compatibility modes for both those compilers, and defines macros indicating (claimed) compatibility with them. If the feature wasn’t implemented in the indicated EDG version, it is assumed that the feature is not available – even though it is possible for a customer of EDG to implement a feature before EDG does.

Fortunately Clang has ways to test specifically for the presence of specific features. But unfortunately, the function-call-like syntax used for such tests won’t work with a standard preprocessor, so this fine new feature winds up adding its own flavor of complexity to the mix.

Also note that this code is only the beginning of a real-world solution. A complete solution would need to take into account more compilers, and also command-line option settings specific to various compilers.

1.2 Characteristics of the proposed solution

To preserve implementers’ freedom to add features in the order that makes the most sense for themselves and their customers, implementers should indicate the availability of each separate feature by adding a definition of a macro with the name corresponding to that feature.

Important note: By recommending the use of these macros, WG21 is not making any feature optional; the absence of a definition for the relevant feature-test macro does not make an implementation that lacks a feature conform to a standard that requires the feature. However, if implementers and programmers follow these recommendations, portability of code between real-world implementations should be improved.

To a first approximation, a feature is identified by the WG21 paper in which it is specified, and by which it is introduced into the working draft of the standard. Not every paper introduces a new feature worth a feature-test macro, but every paper that is not just a collection of issue resolutions is considered a candidate; exceptions are explicitly justified.

For C++14, the feature-test macro name generally consists of some combination of words from the title of the paper. In the future, it is hoped that every paper will include its own recommendations concerning feature-test macro names.

The value specified for a feature-test macro is based on the year and month in which the feature is voted into the working draft. In a case where a feature is subsequently changed in a significant way, but arguably remains the same feature, the value of the macro is changed to indicate the “revision level” of the specification of the feature. However, in most cases it is expected that the presence of a feature can be determined by the presence of any non-zero macro value; for example:

template < typename T > struct use_empty_base_opt : use_empty_base_opt :: integral_constant < bool , stdintegral_constant :: is_empty < T >:: value stdis_emptyvalue #if __cpp_lib_is_final && ! std :: is_final < T >:: value stdis_finalvalue #endif > { } ;

To avoid the user’s namespace, names of macros for language features are prefixed by __cpp_ ; for library features, by __cpp_lib_ . A library feature that doesn’t introduce a new header is expected to be defined by the header(s) that implement the feature.

1.3 Examples

Selecting a more efficient compile-time implementation based on the availability of a feature:

#if __cpp_variadic_using // can use the compile-time efficient, flat inheritance template < typename ... T > struct Callable : T ... { Callable using T :: operator () ... ; } ; #else // fall-back to linear recursion for older compilers template < typename ... T > struct Callable; Callable; template < typename T, typename ... U > T, struct Callable < T, U ...> : T, Callable < U ...> { CallableT, UT, Callable using T :: operator () ; using Callable < U ...>:: operator () ; Callable } ; template < typename T > struct Callable < T > : T { Callable using T :: operator () ; } ; template <> struct Callable <> {} ; Callable #endif

Likewise

#if __cpp_fold_expressions template < typename ... T > auto sum ( T ... args ) { return ( args + ...) ; } sumargsargs #else auto sum () { return 0 ; } sum template < typename T > auto sum ( T t ) { return t; } sumT tt; template ( typename T, typename ... Ts ) T,Ts auto sum ( T t, Ts ... ts ) { return t + sum ( ts ...) ; } sumT t, Tstssumts #endif

Selecting a more efficient run-time implementation based on the availability of a feature:

void update ( std :: set < X >& set, const X & elem, int val ) updatestdsetset,elem,val { auto pos = set . find ( elem ) ; possetfindelem if ( pos == set . end ()) possetend return ; #if __cpp_lib_node_extract auto next = std :: next ( pos ) ; nextstdnextpos auto x = set . extract ( pos ) ; setextractpos x . value (). update ( val ) ; valueupdateval . insert ( next, std :: move ( x )) ; setinsertnext, stdmove #else = * pos; X tmppos; = set . erase ( pos ) ; posseterasepos . update ( val ) ; tmpupdateval . insert ( pos, std :: move ( tmp )) ; setinsertpos, stdmovetmp #endif }

In some cases, the value of a feature-test macro can change over time as the underlying feature changes. To make it easier to follow the evolution of each feature, the tables in this document are grouped by macro name - with a row for each possible value and the proposal(s) associated with it.

Conditionally implementing a feature, based on __cpp_static_assert .

#if __cpp_static_assert # if __cpp_static_assert > 201400 # define Static_Assert ( cond ) static_assert ( cond ) condcond # else # define Static_Assert ( cond ) static_assert ( cond, # cond ) condcond,cond # endif # define Static_Assert_Msg ( cond, msg ) static_assert ( cond, msg ) cond,msgcond,msg #else # define Static_Assert ( cond ) cond # define Static_Assert_Msg ( cond, msg ) cond,msg #endif

Attributes can also change semantics over time, which is why the __has_cpp_attribute facility described below evaluates to a value rather than simply 1 or 0 . This allows a user to conditionally provide a version of nodiscard based on __has_cpp_attribute(nodiscard) :

#if __has_cpp_attribute (nodiscard) >= 201907 // nodiscard has a reason and can // be applied to constructors # define NODISCARD ( msg ) [[ nodiscard ( msg )]] msg # define NODISCARD_CTOR ( msg ) [[ nodiscard ( msg )]] msg #elif __has_cpp_attribute (nodiscard) >= 201603 // nodiscard doesn't have a reason, nor can # define NODISCARD ( msg ) [[ nodiscard ]] msg # define NODISCARD_CTOR ( msg ) msg #else // nodiscard doesn't exist at all yet # define NODISCARD ( msg ) msg # define NODISCARD_CTOR ( msg ) msg #endif

2 Recommendations

2.1 Introduction

For the sake of improved portability between partial implementations of various C++ standards, WG21 (the ISO technical committee for the C++ programming language) recommends that implementers and programmers follow the guidelines in this document concerning feature-test macros.

Implementers who provide a new standard feature should define a macro with the recommended name and value, in the same circumstances under which the feature is available (for example, taking into account relevant command-line options), to indicate the presence of support for that feature.

Programmers who wish to determine whether a feature is available in an implementation should base that determination on the state of the macro with the recommended name. (The absence of a tested feature may result in a program with decreased functionality, or the relevant functionality may be provided in a different way. A program that strictly depends on support for a feature can just try to use the feature unconditionally; presumably, on an implementation lacking necessary support, translation will fail. Therefore, if the most useful purpose for a feature-test macro would be to control the inclusion of a #error directive if the feature is unavailable, that is considered inadequate justification for the macro. Note that the usefulness of a test macro for a feature is completely independent of the usefulness of the feature itself.)

2.2 Testing for the presence of a header: __has_include

It is impossible for a C++ program to directly, reliably, and portably determine whether or not a library header is available for inclusion. Conditionally including a header requires the use of a configuration macro, whose setting can be determined by a configuration-test process at build time (reliable, but less portable), or by some other means (often not reliable or portable).

To solve this general problem, WG21 recommends that programmers use the __has_include feature.

2.2.1 Syntax

h-preprocessing-token:

any preprocessing-token other than >



h-pp-tokens:

h-preprocessing-token

h-pp-tokens h-preprocessing-token

has-include-expression:

__has_include ( header-name )

__has_include ( string-literal )

__has_include ( < h-pp-tokens > )

2.2.2 Semantics

In the first form of the has-include-expression, the parenthesized header-name token is not subject to macro expansion. The second and third forms are considered only if the first form does not match, and the preprocessing tokens are processed just as in normal text.

A has-include-expression shall appear only in the controlling constant expression of a #if or #elif directive ([cpp.cond] 16.1). Prior to the evaluation of such an expression, the source file identified by the parenthesized preprocessing token sequence in each contained has-include-expression is searched for as if that preprocessing token sequence were the pp-tokens in a #include directive, except that no further macro expansion is performed. If such a directive would not satisfy the syntactic requirements of a #include directive, the program is ill-formed. The has-include-expression is replaced by the pp-number 1 if the search for the source file succeeds, and by the pp-number 0 if the search fails.

The #ifdef and #ifndef directives, and the defined conditional inclusion operator, shall treat __has_include as if it were the name of a defined macro. The identifier __has_include shall not appear in any context not mentioned in this section.

2.2.3 Example

This demonstrates a way to use a library optional facility only if it is available. Note that having __has_include(<optional>) succeed is insufficient since on many toolchains, headers may exist in installations but have their contents guarded based on compile flags. For example, the following:

#ifdef __has_include #if __has_include (<optional>) #include <optional> :: optional < int > o; stdoptionalo; #endif #endif int main (){ } main

will still fail to compile with g++ -std=c++14 (using libstdc++).

Hence, we need to do:

#ifdef __has_include # if __has_include (<optional>) # include <optional> # if __cpp_lib_optional >= 201606 # define have_optional 1 # endif # elif __has_include (<experimental/optional>) # include <experimental/optional> # if __cpp_lib_experimental_optional >= 201400 # define have_optional 1 # define experimental_optional 1 # endif #endif #ifndef have_optional # define have_optional 0 #endif

Additionally, the <version> header [P0754R2] is a light-weight header that defines all the standard library feature-test macros. An alternate implementation could be:

#ifndef __has_include # define __has_include ( x ) 0 #endif #if __has_include (<version>) # include <version> #elif __has_include (<optional>) # include <optional> #endif #if __cpp_lib_optional >= 201606 # define have_optional 1 #else # define have_optional 0 #endif

2.3 Testing for the presence of an attribute: __has_cpp_attribute

A C++ program cannot directly, reliably, and portably determine whether or not a standard or vendor-specific attribute is available for use. Testing for attribute support generally requires complex macro logic, as illustrated above for language features in general.

To solve this general problem, WG21 recommends that programmers use the __has_cpp_attribute feature.

2.3.1 Syntax

has-attribute-expression:

__has_cpp_attribute ( attribute-token )

2.3.2 Semantics

A has-attribute-expression shall appear only in the controlling constant expression of a #if or #elif directive ([cpp.cond] 16.1). The has-attribute-expression is replaced by a non-zero pp-number if the implementation supports an attribute with the specified name, and by the pp-number 0 otherwise.

For a standard attribute, the value of the __has_cpp_attribute macro is based on the year and month in which the attribute was voted into the working draft. In the case where the attribute is vendor-specific, the value is implementation-defined. However, in most cases it is expected that the availability of an attribute can be detected by any non-zero result.

The #ifdef and #ifndef directives, and the defined conditional inclusion operator, shall treat __has_cpp_attribute as if it were the name of a defined macro. The identifier __has_cpp_attribute shall not appear in any context not mentioned in this section.

2.3.3 Example

This demonstrates a way to use the attribute [[deprecated]] only if it is available.

#ifndef __has_cpp_attribute # define __has_cpp_attribute ( x ) 0 #endif #if __has_cpp_attribute (deprecated) # define ATTR_DEPRECATED ( msg ) [[ deprecated ( msg )]] msg #else # define ATTR_DEPRECATED ( msg ) msg #endif

3 Policies

SG-10 has adopted a number of policies related to our standard practices for determining and naming macros.

3.1 constexpr

For the language, we will have a single __cpp_constexpr macro. It will be bumped every time we extend constexpr in the language. For the library, we will add a specific feature-test macros for significant, special features. Otherwise, for those cases where we are just adding constexpr to more things in the library, we will have a dedicated test macro per header and just bump that header-specific macro on each change. That macro will be named __cpp_lib_constexpr_HEADER (with the exception of a few preexisting macros for array and algorithm which have slightly different names).

From [P1902R1].

3.2 Language Features with Library Components

In some cases a feature requires two macros, one for the language and one for the library. For example, the library does not want to define its three-way comparison operations unless the compiler supports the feature.

For end-users, it is suggested that they test only the library macro, as that will only be true if the language macro is also true. As a result, the language macros contain “ impl ” to distinguish them from the more general version that is expected to be set by the library.

Note that originally SG10 suggested that the library version of the macro not include the usual _lib part, but LWG was not comfortable with the inconsistency of having a library macro (which requires a header before it can be used) that does not contain _lib .

Also note that SG10 originally proposed that the core feature tests include _lang , but LWG wanted something that more clearly implied that the the macro was for a core feature and not intended to be used by end-users. They sugggested that _impl be used instead.

From [P1353R0].

4 Table of Feature-Test Macros

The following are all the feature-test macros in the standard, broken up by language macros, attribute macros, and library macros, then sorted by name. Each macro will contain its list of possible values and the papers necessary to be implemented before an implementation should define that macro with that particular value.

Note that a given paper may introduce or update multiple feature-test macros. A given value may require multiple papers. A paper may also remove a feature-test macro, in which case its value will be specified as deleted .

4.1 Language Feature-Test Macros

All of the language macros are predefined (i.e. no header needs to be included before doing checks).

In some cases, a feature requires two macros: one for the language and one for the library. For example, the library does not want to define its three-way comparison operators unless the compiler supports the feature. In these cases, it is suggested for end-users that they only test the library macro. Those core language feature-test macros that are intended to be checked by the library are spelled __cpp_impl_* .

Macro Value Paper(s) __cpp_aggregate_bases 201603 P0017R1] __cpp_aggregate_nsdmi 201304 N3653] __cpp_aggregate_paren_init 201902 P0960R3] __cpp_alias_templates 200704 N2258] __cpp_aligned_new 201606 P0035R4] __cpp_attributes 200809 N2761] __cpp_binary_literals 201304 N3472] __cpp_capture_star_this 201603 P0018R3] * this by Value as [= , * this ] __cpp_char8_t 201811 P0482R6] char8_t : A type for UTF-8 characters and strings (Revision 6) __cpp_concepts 201707 P0734R0] 201811 P1084R2] 201907 P1452R2] __cpp_conditional_explicit 201806 P0892R2] explicit ( bool ) __cpp_consteval 201811 P1073R3] __cpp_constexpr 200704 N2235] 201304 N3652] 201603 P0170R1] 201806 P1064R0] 201811 P1002R1]

P1327R1]

P1330R0] 201907 P1331R2]

P1668R1] __cpp_constexpr_dynamic_alloc 201907 P0784R7] __cpp_constexpr_in_decltype 201711 P0859R0] __cpp_constinit 201907 P1143R2] constinit keyword __cpp_decltype 200707 N2343] __cpp_decltype_auto 201304 N3638] __cpp_deduction_guides 201606 P0091R3] 201611 P0512R0] 201703 P0620R0] 201907 P1814R0]

P1816R0] __cpp_delegating_constructors 200604 N1986] __cpp_designated_initializers 201707 P0329R4] __cpp_enumerator_attributes 201411 N4266] __cpp_exceptions 199711 Exception handling __cpp_fold_expressions 201411 N4295] 201603 P0036R0] __cpp_generic_lambdas 201304 N3649] 201707 P0428R2] __cpp_guaranteed_copy_elision 201606 P0135R1] __cpp_hex_float 201603 P0245R1] __cpp_if_constexpr 201606 P0292R2] __cpp_impl_coroutine 201902 P0912R5]

LWG3393] __cpp_impl_destroying_delete 201806 P0722R3] __cpp_impl_three_way_comparison 201711 P0515R3]

P0768R1] 201902 P1185R2] <=> != == 201907 P1630R1] __cpp_inheriting_constructors 200802 N2540] 201511 P0136R1] __cpp_init_captures 201304 N3648] 201803 P0780R2] __cpp_initializer_lists 200806 N2672] __cpp_inline_variables 201606 P0386R2] __cpp_lambdas 200907 N2927] __cpp_modules 201907 P1103R3]

P1811R0] __cpp_namespace_attributes 201411 N4266] __cpp_noexcept_function_type 201510 P0012R1] __cpp_nontype_template_args 201411 N4268] 201911 P1907R1] __cpp_nontype_template_parameter_auto 201606 P0127R2] __cpp_nontype_template_parameter_class 201806 P0732R2] deleted P1907R1] __cpp_nsdmi 200809 N2756] __cpp_range_based_for 200907 N2930] 201603 P0184R0] __cpp_raw_strings 200710 N2442] __cpp_ref_qualifiers 200710 N2439] * this (revised wording) __cpp_return_type_deduction 201304 N3638] __cpp_rtti 199711 Run-time type identification __cpp_rvalue_references 200610 N2118] __cpp_sized_deallocation 201309 N3778] __cpp_static_assert 200410 N1720] 201411 N3928] __cpp_structured_bindings 201606 P0217R3] __cpp_template_template_args 201611 P0522R0] __cpp_threadsafe_static_init 200806 N2660] __cpp_unicode_characters 200704 N2249] __cpp_unicode_literals 200710 N2442] __cpp_user_defined_literals 200809 N2765] __cpp_using_enum 201907 P1099R5] __cpp_variable_templates 201304 N3651] __cpp_variadic_templates 200704 N2242] __cpp_variadic_using 201611 P0195R2] using-declarations

4.2 Attribute Feature-Test Macros

All of the following macros are predefined.

4.3 Library Feature-Test Macros

All of the following macros are defined after inclusion of the header <version> or one of the corresponding headers specified below.

Macro Header(s) Value Paper(s) __cpp_lib_addressof_constexpr < memory > 201603 LWG2296] std :: addressof should be constexpr __cpp_lib_allocator_traits_is_always_equal < deque > < forward_list > < list > < map > < memory > < scoped_allocator > < set > < string > < unordered_map > < unordered_set > < vector > 201411 N4258] noexcept in the Library (Rev 3) __cpp_lib_any < any > 201603 P0220R1] 201606 P0032R3] __cpp_lib_apply < tuple > 201603 P0220R1] __cpp_lib_array_constexpr < array > < iterator > 201603 P0031R0] 201803 P0858R0]

LWG3257] 201806 P1023R0] 201811 P1032R1] __cpp_lib_as_const < utility > 201510 P0007R1] std :: as_const helper function template __cpp_lib_assume_aligned < memory > 201811 P1007R3] __cpp_lib_atomic_flag_test < atomic > 201907 P1135R6] __cpp_lib_atomic_float < atomic > 201711 P0020R6] __cpp_lib_atomic_is_always_lock_free < atomic > 201603 P0152R1] constexpr atomic < T >:: is_always_lock_free __cpp_lib_atomic_lock_free_type_aliases < atomic > 201907 P1135R6] __cpp_lib_atomic_ref < atomic > 201806 P0019R8] __cpp_lib_atomic_shared_ptr < memory > 201711 P0718R2] __cpp_lib_atomic_value_initialization < atomic > < memory > 201911 P0883R2] __cpp_lib_atomic_wait < atomic > 201907 P1135R6] __cpp_lib_barrier < barrier > 201907 P1135R6] __cpp_lib_bind_front < functional > 201811 P0356R5] 201907 P1651R0] __cpp_lib_bit_cast < bit > 201806 P0476R2] __cpp_lib_bitops < bit > 201907 P0553R4] __cpp_lib_bool_constant < type_traits > 201505 N4389] bool_constant , revision 1 __cpp_lib_bounded_array_traits < type_traits > 201902 P1357R1] __cpp_lib_boyer_moore_searcher < functional > 201603 P0220R1] __cpp_lib_byte < cstddef > 201603 P0298R3] __cpp_lib_char8_t < atomic > < filesystem > < istream > < limits > < locale > < ostream > < string > < string_view > 201811 P0482R6] char8_t : A type for UTF-8 characters and strings (Revision 6) 201907 P1423R3] char8_t backward compatibility remediation __cpp_lib_chrono < chrono > 201510 P0092R1] < chrono > 201611 P0505R0] 201803 P0355R7] to Calendars and Time Zones 201907 P1466R3] __cpp_lib_chrono_udls < chrono > 201304 N3642] __cpp_lib_clamp < algorithm > 201603 P0025R0] __cpp_lib_complex_udls < complex > 201309 N3779] std :: complex __cpp_lib_concepts < concepts > 201806 P0898R3] 201907 P1754R1] 202002 P1964R2] boolean - testable __cpp_lib_constexpr_algorithms < algorithm > 201703 P0202R3] < algorithm > and < utility > Headers 201806 P0879R0]

LWG3256] __cpp_lib_constexpr_complex < complex > 201711 P0415R1] __cpp_lib_constexpr_dynamic_alloc < memory > 201907 P0784R7] __cpp_lib_constexpr_functional < functional > 201811 P1032R1] 201907 P1065R2] INVOKE __cpp_lib_constexpr_iterator < iterator > 201811 P1032R1] __cpp_lib_constexpr_memory < memory > 201811 P1006R1] __cpp_lib_constexpr_numeric < numeric > 201911 P1645R1] __cpp_lib_constexpr_string < string > 201611 P0426R1] 201811 P1032R1] 201907 P0980R1] std :: string constexpr __cpp_lib_constexpr_string_view < string_view > 201611 P0426R1] 201811 P1032R1] __cpp_lib_constexpr_tuple < tuple > 201811 P1032R1] __cpp_lib_constexpr_utility < utility > 201811 P1032R1] __cpp_lib_constexpr_vector < vector > 201907 P1004R2] std :: vector constexpr __cpp_lib_coroutine < coroutine > 201902 P0912R5]

LWG3393] __cpp_lib_destroying_delete < new > 201806 P0722R3] __cpp_lib_enable_shared_from_this < memory > 201603 P0033R1] __cpp_lib_endian < bit > 201907 P0463R1]

P1612R1] __cpp_lib_erase_if < deque > < forward_list > < list > < map > < set > < string > < unordered_map > < unordered_set > < vector > 201811 P1209R0] 202002 P1115R3] __cpp_lib_exchange_function < utility > 201304 N3668] exchange () utility function, revision 3 __cpp_lib_execution < execution > 201603 P0024R2] 201902 P1001R2] __cpp_lib_filesystem < filesystem > 201603 P0218R1] 201606 P0219R1]

P0392R0] 201703 P0317R1] __cpp_lib_format < format > 201907 P0645R10]

P1361R2]

P1652R1] __cpp_lib_gcd_lcm < numeric > 201606 P0295R0] __cpp_lib_generic_associative_lookup < map > < set > 201304 N3657] __cpp_lib_generic_unordered_hash_lookup <unordered_map> <unordered_set> 201902 P0920R2] deleted P1661R1] __cpp_lib_generic_unordered_lookup < unordered_map > < unordered_set > 201811 P0919R3] __cpp_lib_hardware_interference_size < new > 201703 P0154R1] constexpr std :: thread :: hardware_ { true , false } _sharing_size __cpp_lib_has_unique_object_representations < type_traits > 201606 P0258R2] __cpp_lib_hypot < cmath > 201603 P0030R1] __cpp_lib_incomplete_container_elements < forward_list > < list > < vector > 201505 N4510] __cpp_lib_int_pow2 < bit > 201806 P0556R3] 202002 P1956R1] __cpp_lib_integer_comparison_functions < utility > 202002 P0586R2] __cpp_lib_integer_sequence < utility > 201304 N3658] __cpp_lib_integral_constant_callable < type_traits > 201304 N3545] integral_constant __cpp_lib_interpolate < cmath > < numeric > 201902 P0811R3] __cpp_lib_invoke < functional > 201411 N4169] invoke function template (Revision 1) __cpp_lib_is_aggregate < type_traits > 201703 LWG2911] is_aggregate type trait is needed __cpp_lib_is_constant_evaluated < type_traits > 201811 P0595R2] std :: is_constant_evaluated __cpp_lib_is_final < type_traits > 201402 LWG2112] __cpp_lib_is_invocable < type_traits > 201703 P0604R0] __cpp_lib_is_layout_compatible < type_traits > 201907 P0466R5] __cpp_lib_is_nothrow_convertible < type_traits > 201806 P0758R1]

LWG3356] __cpp_lib_is_null_pointer < type_traits > 201309 LWG2247] std :: nullptr_t __cpp_lib_is_pointer_interconvertible < type_traits > 201907 P0466R5] __cpp_lib_is_swappable < type_traits > 201603 P0185R1] __cpp_lib_jthread < stop_token > < thread > 201907 P0660R10] 201911 P1869R1] __cpp_lib_latch < latch > 201907 P1135R6] __cpp_lib_launder < new > 201606 P0137R1] __cpp_lib_list_remove_return_type < forward_list > < list > 201806 P0646R1] __cpp_lib_logical_traits < type_traits > 201510 P0013R1] __cpp_lib_make_from_tuple < tuple > 201606 P0209R2] make_from_tuple : apply for construction __cpp_lib_make_reverse_iterator < iterator > 201402 LWG2285] make_reverse_iterator __cpp_lib_make_unique < memory > 201304 N3656] make_unique (Revision 1) __cpp_lib_map_try_emplace < map > 201411 N4279] __cpp_lib_math_constants < numbers > 201907 P0631R8] __cpp_lib_math_special_functions < cmath > 201603 P0226R1] __cpp_lib_memory_resource < memory_resource > 201603 P0220R1] __cpp_lib_node_extract < map > < set > < unordered_map > < unordered_set > 201606 P0083R3] __cpp_lib_nonmember_container_access < array > < deque > < forward_list > < iterator > < list > < map > < regex > < set > < string > < unordered_map > < unordered_set > < vector > 201411 N4280] __cpp_lib_not_fn < functional > 201603 P0005R4] not_fn from Library Fundamentals 2 for C++17 __cpp_lib_null_iterators < iterator > 201304 N3644] __cpp_lib_optional < optional > 201603 P0220R1] 201606 P0032R3]

P0307R2] __cpp_lib_parallel_algorithm < algorithm > < numeric > 201603 P0024R2] __cpp_lib_polymorphic_allocator < memory > 201902 P0339R6] __cpp_lib_quoted_string_io < iomanip > 201304 N3654] __cpp_lib_ranges < algorithm > < functional > < iterator > < memory > < ranges > 201811 P0896R4] 201907 P1035R7] 201911 P1716R3] __cpp_lib_raw_memory_algorithms < memory > 201606 P0040R3] __cpp_lib_remove_cvref < type_traits > 201711 P0550R2] __cpp_lib_result_of_sfinae < functional > < type_traits > 201210 N3462] std :: result_of and SFINAE __cpp_lib_robust_nonmodifying_seq_ops < algorithm > 201304 N3671] __cpp_lib_sample < algorithm > 201603 P0220R1] __cpp_lib_scoped_lock < mutex > 201703 P0156R2] lock_guard (Rev. 4) __cpp_lib_semaphore < semaphore > 201907 P1135R6] __cpp_lib_shared_mutex < shared_mutex > 201505 N4508] __cpp_lib_shared_ptr_arrays < memory > 201611 P0497R0] 201707 P0674R1] __cpp_lib_shared_ptr_weak_type < memory > 201606 P0163R0] shared_ptr :: weak_type __cpp_lib_shared_timed_mutex < shared_mutex > 201402 N3891] shared_mutex to shared_timed_mutex __cpp_lib_shift < algorithm > 201806 P0769R2] < algorithm > __cpp_lib_smart_ptr_for_overwrite < memory > 202002 P1020R1]

P1973R1] __cpp_lib_source_location < source_location > 201907 P1208R6] __cpp_lib_span < span > 201803 P0122R7]

LWG3274] < span > 201902 P1024R3] std :: span 202002 P1976R2] span construction from dynamic range __cpp_lib_ssize < iterator > 201902 P1227R2] __cpp_lib_starts_ends_with < string > < string_view > 201711 P0457R2] __cpp_lib_string_udls < string > 201304 N3642] __cpp_lib_string_view < string > < string_view > 201603 P0220R1] 201606 P0254R2] std :: string_view and std :: string 201803 P0858R0]

LWG3257] __cpp_lib_syncbuf < syncstream > 201711 P0053R7] 201803 P0753R2] __cpp_lib_three_way_comparison < compare > 201711 P0768R1] 201907 P1614R2] <=> to the Library __cpp_lib_to_address < memory > 201711 P0653R2] __cpp_lib_to_array < array > 201907 P0325R4] __cpp_lib_to_chars < charconv > 201611 P0067R5]

P0682R1]

LWG3137] __cpp_lib_to_chars __cpp_lib_transformation_trait_aliases < type_traits > 201304 N3655] __cpp_lib_transparent_operators < functional > < memory > 201210 N3421] greater <> 201510 P0074R0] std :: owner_less more flexible __cpp_lib_tuple_element_t < tuple > 201402 N3887] __cpp_lib_tuples_by_type < tuple > < utility > 201304 N3670] __cpp_lib_type_identity < type_traits > 201806 P0887R1] __cpp_lib_type_trait_variable_templates < type_traits > 201510 P0006R0] __cpp_lib_uncaught_exceptions < exception > 201411 N4259] std :: uncaught_exceptions __cpp_lib_unordered_map_try_emplace < unordered_map > 201411 N4279] __cpp_lib_unwrap_ref < functional > 201811 P0318R1]

LWG3348] __cpp_lib_variant < variant > 201606 P0088R3]

P0393R3]

P0032R3] __cpp_lib_void_t < type_traits > 201411 N3911] void_t

5 References