Users of freestanding implementations would like to be able to detect which library facilities are available for use. With the C++20 feature-test macros, all the feature-test macros are required to be defined in both freestanding and hosted implementations, even when the associated hosted facilities are not available. This paper will make the presence of feature-test macros for hosted facilities implementation-defined. This paper will also bump the version number on all library feature-test macros, so that extensions can be detected.
This paper also clarifies that freestanding implementations need not stop at the bare minimum support for freestanding. Freestanding implementations may provide additional facilities from the standard library, so long as those facilities meet the associated hosted requirements.
This paper grants implementations the freedom to include more than just the facilities that are marked //freestanding
.
There will be platforms where, for example, floating point is both available and frequently used (e.g. GPU environments).
On those platforms, it is desirable for implementations to provide many of the facilities in the <cmath>
and <complex>
headers.
We must be careful here though, as we don't want to allow divergence of implementation, and we want to be able to add facilities to the required subset of freestanding.
To permit both vendor extension and future freestanding growth, this paper will require that additionally included facilities must meet the same requirements as for a hosted implementation, with a few exceptions.
Freestanding implementations may include additional macros and namespace scoped entities, beyond what is required in a minimal freestanding implementation.
A freestanding implementation does not need to provide the entirety of a header.
If a freestanding implementation supplies an additional class, the entirety of the class must be present and meet all the hosted requirements.
This prevents some useful vendor extensions, notably at()
-less array
, value()
-less optional
, and similarly partial string_view
and bitset
.
This does not prevent us from standardizing a partial class in the future, though it does prevent us from getting usage experience in a conforming implementation.
Freestanding implementations may make the use of any non-freestanding, namespace scoped function or function template ill-formed (e.g. generally by marking it =delete
). The intent is to allow the freestanding implementation to control overload resolution, so that a library that works with a freestanding implementation will have the same semantics in a hosted implementation.
Users will be able to rely on the freestanding portions of the standard library. The freestanding portions have portable semantics, and are required to be present. Users may then decide to rely on implementation-defined additions. WG21 will be able to add hosted entities to the freestanding subset without little fear of breaking implementation-defined additions, because the implementation-defined additions needed to meet the hosted requirements.
C++20 requires that all implementations (freestanding and hosted) define all of the library feature-test macros in the <version>
header, even the feature-test macros that correspond to facilities not required to be present in freestanding implementations.
This means that those feature-test macros provide misleading results on freestanding implementations.
This isn't just a theoretical problem.
Existing implementations are already deploying <version>
headers that report support for std::filesystem
facilities, std::chrono
facilities, and many others, even though those feature-test macros indicate support for features that require the support of an operating system.
In order for users of freestanding implementations to be able to detect extensions of freestanding, the users need a way of distinguishing the C++20 macro requirements from an accurate expression of extension. This paper will bump all library macro versions, so that users can distinguish between these cases.
<version>
header are not required to be present on freestanding implementations.
The corresponding facilities were either required to be present in C++20, or are added in P1642.
__cpp_lib_addressof_constexpr
__cpp_lib_allocator_traits_is_always_equal
__cpp_lib_apply
__cpp_lib_as_const
__cpp_lib_assume_aligned
__cpp_lib_atomic_flag_test
__cpp_lib_atomic_float
__cpp_lib_atomic_is_always_lock_free
__cpp_lib_atomic_ref
__cpp_lib_atomic_value_initialization
__cpp_lib_atomic_wait
__cpp_lib_bind_front
__cpp_lib_bit_cast
__cpp_lib_bitops
__cpp_lib_bool_constant
__cpp_lib_bounded_array_traits
__cpp_lib_byte
__cpp_lib_char8_t
__cpp_lib_concepts
__cpp_lib_constexpr_functional
__cpp_lib_constexpr_iterator
__cpp_lib_constexpr_memory
__cpp_lib_constexpr_tuple
__cpp_lib_constexpr_utility
__cpp_lib_destroying_delete
__cpp_lib_endian
__cpp_lib_exchange_function
__cpp_lib_hardware_interference_size
__cpp_lib_has_unique_object_representations
__cpp_lib_int_pow2
__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_layout_compatible
__cpp_lib_is_nothrow_convertible
__cpp_lib_is_null_pointer
__cpp_lib_is_pointer_interconvertible
__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_remove_cvref
__cpp_lib_result_of_sfinae
__cpp_lib_source_location
__cpp_lib_ssize
__cpp_lib_three_way_comparison
__cpp_lib_to_address
__cpp_lib_transformation_trait_aliases
__cpp_lib_transparent_operators
__cpp_lib_tuple_element_t
__cpp_lib_tuples_by_type
__cpp_lib_type_identity
__cpp_lib_type_trait_variable_templates
__cpp_lib_uncaught_exceptions
__cpp_lib_unwrap_ref
__cpp_lib_void_t
Users of freestanding implementations will want to know whether including a formerly hosted-only header will work or not. Users of freestanding implementations will also what to know if all the facilities that are required to be in freestanding have been made available yet. This is a concern for highly portable libraries, and for users that need to support old and new compilers.
These feature-test macros are provided at a per-header granularity.
This enables implementations to advertise new capabilities more easily than a single feature-test macro for the entirety of this paper.
This also follows the precedent set by the __cpp_lib_constexpr_*
macros.
If new, pre-C++20 functionality is added to the freestanding subset of C++, then the respective feature-test macro for the header should be bumped. If the functionality is new in C++23 or later, then alternative approaches should be taken. These alternative approaches are discussed in the examples section.
Name | Header |
---|---|
__cpp_lib_freestanding_utility |
<utility> |
__cpp_lib_freestanding_tuple |
<tuple> |
__cpp_lib_freestanding_ratio |
<ratio> |
__cpp_lib_freestanding_memory |
<memory> |
__cpp_lib_freestanding_functional |
<functional> |
__cpp_lib_freestanding_iterator |
<iterator> |
__cpp_lib_freestanding_ranges |
<ranges> |
The following, existing feature-test macros cover some features that I am making freestanding, and some features that I am not requiring to be freestanding.
These feature-test macros won't be required in freestanding, as they could cause substantial confusion when the hosted parts of those features aren't available.
The per-header __cpp_lib_freestanding_*
macros should provide a suitable replacement in freestanding environments.
__cpp_lib_boyer_moore_searcher
: default_searcher
is in, other searchers require the heap.__cpp_lib_constexpr_dynamic_alloc
: constexpr
ification of various memory algorithms is in, anything dealing with std::allocator
is out__cpp_lib_ranges
: stream iterators are out__cpp_lib_raw_memory_algorithms
: ExecutionPolicy overloads are outThis paper patches up many of the historical problems with freestanding and feature-test macros. The following are the guidelines I recommend to keep feature-test macros useful for freestanding in the future.
__cpp_lib_foo
will cover the full paper in the hosted case, and __cpp_lib_freestanding_foo
will cover the freestanding portions.__cpp_lib_freestanding_foo
.-Wundef
.filesystem::copy
available?
#if __STDC_HOSTED__ && defined(__cpp_lib_filesystem) && __cpp_lib_filesystem >= 201703L // hosted success path #elif defined(__cpp_lib_filesystem) && __cpp_lib_filesystem >= 202007L // freestanding extension path #else // fallback path #endif
ssize
available?
#if __STDC_HOSTED__ && defined(__cpp_lib_ssize) && __cpp_lib_ssize >= 201902L // hosted success path #elif defined(__cpp_lib_ssize) && __cpp_lib_ssize >= 202007L // freestanding path #else // fallback path #endif
uninitialized_default_construct
available?
#if defined(__cpp_lib_raw_memory_algorithms) && __cpp_lib_raw_memory_algorithms >= 201606L // hosted success path and freestanding extension path #elif defined(__cpp_lib_freestanding_memory) && __cpp_lib_freestanding_memory >= 202007L // freestanding path #else // fallback path #endif
tuple
available?
#if defined(__cpp_lib_freestanding_tuple) && __cpp_lib_freestanding_tuple >= 202007L // freestanding and future hosted success path #elif __STDC_HOSTED__ // flakey hosted success path. Assume tuple works here #else // fallback path #endif
thread
available?
// No good answers here. Currently calling this out of scope.
#if defined(__cpp_lib_always_freestanding_feature) && __cpp_lib_always_freestanding_feature >= 202202L // hosted and freestanding success path #else // fallback path #endif
#if defined(__cpp_lib_eventually_freestanding_feature) #if __cpp_lib_eventually_freestanding_feature >= 202702L // freestanding success path. Will also trigger for new hosted toolchains #elif __STDC_HOSTED__ && __cpp_lib_eventually_freestanding_feature >= 202102L // Interim hosted success path #else // Interim freestanding fallback path #endif #else // fallback path #endif // Alternative that will work 99% of the time #if defined(__cpp_lib_eventually_freestanding_feature) // freestanding and hosted success, probably #else // fallback path #endif
__cpp_lib_foo
for the full paper, and __cpp_lib_freestanding_foo
for the freestanding portion.#if defined(__cpp_lib_freestanding_foo) && __cpp_lib_freestanding_foo >= 202202L // hosted and freestanding success path #else // fallback path #endif
__cpp_lib_freestanding_bar
for the freestanding portion.#if defined(__cpp_lib_bar) && __cpp_lib_bar >= 202202L // Old hosted toolchain path and freestanding extension path #elif defined(__cpp_lib_freestanding_bar) && __cpp_lib_freestanding_bar >= 202702L // freestanding success path. Will also trigger for new hosted toolchains #else // fallback path #endif
Allowing partial classes gives implementers a great deal of freedom to experiment and to provide extensions.
It also permits abuse by the implementers.
On the positive side, an implementation could provide std::array
without at
.
This helps replace C facilities with better facilities from C++.
On the negative side, an implementation could =delete
the copy constructor.
Removing the wrong functions would also mean that a class may not satisfy the same concepts in hosted vs. freestanding.
Rather than have a __cpp_lib_freestanding_ratio
(for example), we could instead update __cpp_lib_chrono
.
Users could test the value of __cpp_lib_chrono
to determine if it is freestanding safe or not.
There are at least two big flaws with this approach.
First, not all facilities (particularly older ones) have existing feature-test macros to bump (e.g. unique_ptr
).
Users would still like to be able to detect the availability of the features in freestanding.
Second, implementers don't always implement features in the same order that they are added to the working draft.
If a new feature were added to the <chrono>
header that necessitated a feature-test macro bump, and an implementer addressed that feature before making the <ratio>
header freestanding safe, then the implementer would either need to stick with the pre-freestanding feature-test macro version, or provide a misleading feature-test macro version.
Rather than introduce a feature-test macro per header in this paper, I could instead introduce one feature-test macro... perhaps __cpp_lib_freestanding
. Each paper that adds old facilities to freestanding could then introduce it's own macro, or bump the old one.
This approach can work, but it restricts the order in which implementers can meaningfully implement freestanding features. All of the old paper needs to be done before any of the old paper's progress can be advertised. All of the old paper needs to be done before advertising any newer papers.
This paper could choose to add a feature-test macro for __cpp_lib_freestanding_unique_ptr
, __cpp_lib_freestanding_pair
, and __cpp_lib_freestanding_iterator_categories
.
There would be some value to users in that they could express exactly what it is they need, and see if that very specific facility is available.
However, this approach is an implementation hassle, and prone to endless wg21 debates on how to partition and name the facilities. Grouping facilities by header provides a natural partitioning and naming scheme.
__has_include
Some have suggested using __has_include
to detect whether the <tuple>
header (for example) is usable on a particular freestanding implementation.
This doesn't work in practice for multiple reasons.
<iterator>
header.
In older versions of Visual Studio, a user could attempt to #include <iterator>
.
The streaming iterators in the header result in compiler errors.
We need feature-test macros to indicate whether including the header is well-formed.
The second example is headers that do standard versions checks inside.
The libstdc++ implementation of the <ranges>
header is mostly empty if the language version is less than C++20.
__has_include
will still report the header as present though.
This makes it even more difficult to detect extensions to freestanding. Existing implementations report support for __cpp_lib_filesystem
when the -ffreestanding
flag is passed, even though it is unlikely that filesystem is supported on such platforms. The C++20 standard currently requires this behavior.
__cpp_lib_freestanding_*
macros freestanding onlyThis complicates the client feature-test code for features that were marked freestanding in their initial papers. It doesn't make any of the client feature-test code any simpler. It also violates the principle that freestanding should be a subset of hosted.
__cpp_lib_freestanding_*
macros to 0 in hosted
Users of the freestanding macros would still need to account for the case where the macro isn't present.
Defining the macro to zero doesn't provide any information beyond what __STDC_HOSTED__
provides.
Please append the following paragraphs to [compliance].
The hosted library facilities are the set of facilities described in this document that are required for hosted implementations, but not required for freestanding implementations.A freestanding implementation provides a (possibly empty) implementation-defined subset of the hosted library facilities.Unless otherwise specified, the requirements on each macro and namespace scoped entity provided in this way shall be the same as the corresponding requirements in a hosted implementation.A freestanding implementation provides deleted definitions for a (possibly empty) implementation-defined subset of the namespace scoped functions and function templates from the hosted library facilities.[ Note: An implementation may provide a deleted definition so that overload resolution does not silently change when migrating a library from a freestanding implementation to a hosted implementation. -end note]
Please make the following changes to [version.syn]. Use the current year-based constant instead of "new-val".
#define __cpp_lib_addressof_constexpr201603Lnew-val // freestanding, also in <memory> #define __cpp_lib_allocator_traits_is_always_equal201411Lnew-val // freestanding, also in <memory>, <scoped-allocator>, <string>, <deque>, <forward-list>, <list>, <vector>, // <map>, <set>, <unordered-map>, <unordered-set> #define __cpp_lib_any201606Lnew-val // also in <any> #define __cpp_lib_apply201603Lnew-val // freestanding, also in <tuple> #define __cpp_lib_array_constexpr201811Lnew-val // also in <iterator>, <array> #define __cpp_lib_as_const201510Lnew-val // freestanding, also in <utility> #define __cpp_lib_assume_aligned201811Lnew-val // freestanding, also in <memory> #define __cpp_lib_atomic_flag_test201907Lnew-val // freestanding, also in <atomic> #define __cpp_lib_atomic_float201711Lnew-val // freestanding, also in <atomic> #define __cpp_lib_atomic_is_always_lock_free201603Lnew-val // freestanding, also in <atomic> #define __cpp_lib_atomic_lock_free_type_aliases201907Lnew-val // also in <atomic> #define __cpp_lib_atomic_ref201806Lnew-val // freestanding, also in <atomic> #define __cpp_lib_atomic_shared_ptr201711Lnew-val // also in <memory> #define __cpp_lib_atomic_value_initialization201911Lnew-val // freestanding, also in <atomic>, <memory> #define __cpp_lib_atomic_wait201907Lnew-val // freestanding, also in <atomic> #define __cpp_lib_barrier201907Lnew-val // also in <barrier> #define __cpp_lib_bind_front201907Lnew-val // freestanding, also in <functional> #define __cpp_lib_bit_cast201806Lnew-val // freestanding, also in <bit> #define __cpp_lib_bitops201907Lnew-val // freestanding, also in <bit> #define __cpp_lib_bool_constant201505Lnew-val // freestanding, also in <type-traits> #define __cpp_lib_bounded_array_traits201902Lnew-val // freestanding, also in <type-traits> #define __cpp_lib_boyer_moore_searcher201603Lnew-val // also in <functional> #define __cpp_lib_byte201603Lnew-val // freestanding, also in <cstddef> #define __cpp_lib_char8_t201907Lnew-val // freestanding, also in <atomic>, <filesystem>, <istream>, <limits>, <locale>, <ostream>, <string>, <string-view> #define __cpp_lib_chrono201907Lnew-val // also in <chrono> #define __cpp_lib_chrono_udls201304Lnew-val // also in <chrono> #define __cpp_lib_clamp201603Lnew-val // also in <algorithm> #define __cpp_lib_complex_udls201309Lnew-val // also in <complex> #define __cpp_lib_concepts202002Lnew-val // freestanding, also in <concepts> #define __cpp_lib_constexpr_algorithms201806Lnew-val // also in <algorithm> #define __cpp_lib_constexpr_complex201711Lnew-val // also in <complex> #define __cpp_lib_constexpr_dynamic_alloc201907Lnew-val // also in <memory> #define __cpp_lib_constexpr_functional201907Lnew-val // freestanding, also in <functional> #define __cpp_lib_constexpr_iterator201811Lnew-val // freestanding, also in <iterator> #define __cpp_lib_constexpr_memory201811Lnew-val // freestanding, also in <memory> #define __cpp_lib_constexpr_numeric201911Lnew-val // also in <numeric> #define __cpp_lib_constexpr_string201907Lnew-val // also in <string> #define __cpp_lib_constexpr_string_view201811Lnew-val // also in <string-view> #define __cpp_lib_constexpr_tuple201811Lnew-val // freestanding, also in <tuple> #define __cpp_lib_constexpr_utility201811Lnew-val // freestanding, also in <utility> #define __cpp_lib_constexpr_vector201907Lnew-val // also in <vector> #define __cpp_lib_coroutine201902Lnew-val // also in <coroutine> #define __cpp_lib_destroying_delete201806Lnew-val // freestanding, also in <new> #define __cpp_lib_enable_shared_from_this201603Lnew-val // also in <memory> #define __cpp_lib_endian201907Lnew-val // freestanding, also in <bit> #define __cpp_lib_erase_if202002Lnew-val // also in <string>, <deque>, <forward-list>, <list>, <vector>, <map>, <set>, <unordered-map>, // <unordered-set> #define __cpp_lib_exchange_function201304Lnew-val // freestanding, also in <utility> #define __cpp_lib_execution201902Lnew-val // also in <execution> #define __cpp_lib_filesystem201703Lnew-val // also in <filesystem> #define __cpp_lib_format201907Lnew-val // also in <format> #define __cpp_lib_freestanding_functional new-val // freestanding, also in <functional> #define __cpp_lib_freestanding_iterator new-val // freestanding, also in <iterator> #define __cpp_lib_freestanding_memory new-val // freestanding, also in <memory> #define __cpp_lib_freestanding_ranges new-val // freestanding, also in <ranges> #define __cpp_lib_freestanding_ratio new-val // freestanding, also in <ratio> #define __cpp_lib_freestanding_tuple new-val // freestanding, also in <tuple> #define __cpp_lib_freestanding_utility new-val // freestanding, also in <utility> #define __cpp_lib_gcd_lcm201606Lnew-val // also in <numeric> #define __cpp_lib_generic_associative_lookup201304Lnew-val // also in <map>, <set> #define __cpp_lib_generic_unordered_lookup201811Lnew-val // also in <unordered-map>, <unordered-set> #define __cpp_lib_hardware_interference_size201703Lnew-val // freestanding, also in <new> #define __cpp_lib_has_unique_object_representations201606Lnew-val // freestanding, also in <type-traits> #define __cpp_lib_hypot201603Lnew-val // also in <cmath> #define __cpp_lib_incomplete_container_elements201505Lnew-val // also in <forward-list>, <list>, <vector> #define __cpp_lib_int_pow2202002Lnew-val // freestanding, also in <bit> #define __cpp_lib_integer_comparison_functions202002Lnew-val // also in <utility> #define __cpp_lib_integer_sequence201304Lnew-val // freestanding, also in <utility> #define __cpp_lib_integral_constant_callable201304Lnew-val // freestanding, also in <type-traits> #define __cpp_lib_interpolate201902Lnew-val // also in <cmath>, <numeric> #define __cpp_lib_invoke201411Lnew-val // freestanding, also in <functional> #define __cpp_lib_is_aggregate201703Lnew-val // freestanding, also in <type-traits> #define __cpp_lib_is_constant_evaluated201811Lnew-val // freestanding, also in <type-traits> #define __cpp_lib_is_final201402Lnew-val // freestanding, also in <type-traits> #define __cpp_lib_is_invocable201703Lnew-val // freestanding, also in <type-traits> #define __cpp_lib_is_layout_compatible201907Lnew-val // freestanding, also in <type-traits> #define __cpp_lib_is_nothrow_convertible201806Lnew-val // freestanding, also in <type-traits> #define __cpp_lib_is_null_pointer201309Lnew-val // freestanding, also in <type-traits> #define __cpp_lib_is_pointer_interconvertible201907Lnew-val // freestanding, also in <type-traits> #define __cpp_lib_is_swappable201603Lnew-val // freestanding, also in <type-traits> #define __cpp_lib_jthread201911Lnew-val // also in <stop-token>, <thread> #define __cpp_lib_latch201907Lnew-val // also in <latch> #define __cpp_lib_launder201606Lnew-val // freestanding, also in <new> #define __cpp_lib_list_remove_return_type201806Lnew-val // also in <forward-list>, <list> #define __cpp_lib_logical_traits201510Lnew-val // freestanding, also in <type-traits> #define __cpp_lib_make_from_tuple201606Lnew-val // freestanding, also in <tuple> #define __cpp_lib_make_reverse_iterator201402Lnew-val // freestanding, also in <iterator> #define __cpp_lib_make_unique201304Lnew-val // also in <memory> #define __cpp_lib_map_try_emplace201411Lnew-val // also in <map> #define __cpp_lib_math_constants201907Lnew-val // also in <numbers> #define __cpp_lib_math_special_functions201603Lnew-val // also in <cmath> #define __cpp_lib_memory_resource201603Lnew-val // also in <memory-resource> #define __cpp_lib_node_extract201606Lnew-val // also in <map>, <set>, <unordered-map>, <unordered-set> #define __cpp_lib_nonmember_container_access201411Lnew-val // freestanding, also in <array>, <deque>, <forward-list>, <iterator>, <list>, <map>, <regex>, <set>, <string>, // <unordered-map>, <unordered-set>, <vector> #define __cpp_lib_not_fn201603Lnew-val // freestanding, also in <functional> #define __cpp_lib_null_iterators201304Lnew-val // freestanding, also in <iterator> #define __cpp_lib_optional201606Lnew-val // also in <optional> #define __cpp_lib_parallel_algorithm201603Lnew-val // also in <algorithm>, <numeric> #define __cpp_lib_polymorphic_allocator201902Lnew-val // also in <memory> #define __cpp_lib_quoted_string_io201304Lnew-val // also in <iomanip> #define __cpp_lib_ranges201911Lnew-val // also in <algorithm>, <functional>, <iterator>, <memory>, <ranges> #define __cpp_lib_raw_memory_algorithms201606Lnew-val // also in <memory> #define __cpp_lib_remove_cvref201711Lnew-val // freestanding, also in <type-traits> #define __cpp_lib_result_of_sfinae201210Lnew-val // freestanding, also in <functional>, <type-traits> #define __cpp_lib_robust_nonmodifying_seq_ops201304Lnew-val // also in <algorithm> #define __cpp_lib_sample201603Lnew-val // also in <algorithm> #define __cpp_lib_scoped_lock201703Lnew-val // also in <mutex> #define __cpp_lib_semaphore201907Lnew-val // also in <semaphore> #define __cpp_lib_shared_mutex201505Lnew-val // also in <shared-mutex> #define __cpp_lib_shared_ptr_arrays201707Lnew-val // also in <memory> #define __cpp_lib_shared_ptr_weak_type201606Lnew-val // also in <memory> #define __cpp_lib_shared_timed_mutex201402Lnew-val // also in <shared-mutex> #define __cpp_lib_shift201806Lnew-val // also in <algorithm> #define __cpp_lib_smart_ptr_for_overwrite202002Lnew-val // also in <memory> #define __cpp_lib_source_location201907Lnew-val // freestanding, also in <source-location> #define __cpp_lib_span202002Lnew-val // also in <span> #define __cpp_lib_ssize201902Lnew-val // freestanding, also in <iterator> #define __cpp_lib_starts_ends_with201711Lnew-val // also in <string>, <string-view> #define __cpp_lib_string_udls201304Lnew-val // also in <string> #define __cpp_lib_string_view201803Lnew-val // also in <string>, <string-view> #define __cpp_lib_syncbuf201803Lnew-val // also in <syncstream> #define __cpp_lib_three_way_comparison201907Lnew-val // freestanding, also in <compare> #define __cpp_lib_to_address201711Lnew-val // freestanding, also in <memory> #define __cpp_lib_to_array201907Lnew-val // also in <array> #define __cpp_lib_to_chars201611Lnew-val // also in <charconv> #define __cpp_lib_transformation_trait_aliases201304Lnew-val // freestanding, also in <type-traits> #define __cpp_lib_transparent_operators201510Lnew-val // freestanding, also in <memory>, <functional> #define __cpp_lib_tuple_element_t201402Lnew-val // freestanding, also in <tuple> #define __cpp_lib_tuples_by_type201304Lnew-val // freestanding, also in <utility>, <tuple> #define __cpp_lib_type_identity201806Lnew-val // freestanding, also in <type-traits> #define __cpp_lib_type_trait_variable_templates201510Lnew-val // freestanding, also in <type-traits> #define __cpp_lib_uncaught_exceptions201411Lnew-val // freestanding, also in <exception> #define __cpp_lib_unordered_map_try_emplace201411Lnew-val // also in <unordered-map> #define __cpp_lib_unwrap_ref201811Lnew-val // freestanding, also in <type-traits> #define __cpp_lib_variant201606Lnew-val // also in <variant> #define __cpp_lib_void_t201411Lnew-val // freestanding, also in <type-traits>