W3cubDocs

/C++

Feature testing (since C++20)

The standard defines a set of preprocessor macros corresponding to C++ language and library features introduced in C++11 or later. They are intended as a simple and portable way to detect the presence of said features.

Attributes

__has_cpp_attribute( attribute-token )

Checks for the support of an attribute named by attribute-token (after macro expansion).

For each standard attribute, it is implementation-defined whether __has_cpp_attribute expands to the year and month in which the attribute was added to the working draft (see table below) or ​0​. It is recommended that non-zero value is given if and only if the standard attribute causes the implementation to behave as recommended (issuing diagnostic messages, affecting class layout, etc.).

The presence of vendor-specific attributes is determined by a non-zero value.

__has_cpp_attribute can be expanded in the expression of #if and #elif. It is treated as a defined macro by #ifdef, #ifndef, #elifdef, #elifndef (since C++23) and defined but cannot be used anywhere else.

attribute-token Attribute Value Standard Paper(s)
assume [[assume]] 202207L (C++23) P1774R8
carries_dependency [[carries_dependency]] 200809L (C++11) N2556, N2643
deprecated [[deprecated]] 201309L (C++14) N3760
fallthrough [[fallthrough]] 201603L (C++17) P0188R1
likely [[likely]] 201803L (C++20) P0479R5
maybe_unused [[maybe_unused]] 201603L (C++17) P0212R1
no_unique_address [[no_unique_address]] 201803L (C++20) P0840R2
nodiscard [[nodiscard]] 201603L (C++17) P0189R1
201907L (C++20) P1301R4
noreturn [[noreturn]] 200809L (C++11) N2761
unlikely [[unlikely]] 201803L (C++20) P0479R5
Total number of attributes: 10

Language features

The following macros are predefined in every translation unit. Each macro expands to an integer literal corresponding to the year and month when the corresponding feature has been included in the working draft.

When a feature changes significantly, the macro will be updated accordingly.

Macro name Feature Value Std Paper(s)
__cpp_aggregate_bases Aggregate classes with base classes 201603L (C++17) P0017R1
__cpp_aggregate_nsdmi Aggregate classes with default member initializers 201304L (C++14) N3653
__cpp_aggregate_paren_init Aggregate initialization in the form of direct initialization 201902L (C++20) P0960R3
__cpp_alias_templates Alias templates 200704L (C++11) N2258
__cpp_aligned_new Dynamic memory allocation for over-aligned data 201606L (C++17) P0035R4
__cpp_attributes Attributes 200809L (C++11) N2761
__cpp_auto_cast auto(x) and auto{x} 202110L (C++23) P0849R8
__cpp_binary_literals Binary literals 201304L (C++14) N3472
__cpp_capture_star_this Lambda capture of *this by value as [=,*this] 201603L (C++17) P0018R3
__cpp_char8_t char8_t 201811L (C++20) P0482R6
char8_t compatibility and portability fix (allow initialization of (unsigned) char arrays from UTF-8 string literals) 202207L (C++20)
(DR)
P2513R4
__cpp_concepts Concepts 201907L (C++20) P0734R0
P1084R2
P1452R2
Conditional trivial special member functions 202002L (C++20) P0848R3
P2493R0
__cpp_conditional_explicit explicit(bool) 201806L (C++20) P0892R2
__cpp_consteval Immediate functions 201811L (C++20) P1073R3
Making consteval propagate up 202211L (C++20)
(DR)
P2564R3
__cpp_constexpr constexpr 200704L (C++11) N2235
Relaxed constexpr, non-const constexpr methods 201304L (C++14) N3652
Constexpr lambda 201603L (C++17) P0170R1
Virtual function calls in constant expressions 201806L (C++20) P1064R0
try-catch blocks in consexpr functions, dynamic_cast and polymorphic typeid in constant expressions 201811L (C++20) P1002R1
P1327R1
Trivial default initialization and asm-declaration in constexpr functions 201907L (C++20) P1331R2
P1668R1
Changing the active member of a union in constant evaluation 202002L (C++20) P1330R0
Non-literal variables, labels, and goto statements in constexpr functions 202110L (C++23) P2242R3
Relaxing some restrictions on constexpr functions and function templates 202207L (C++23) P2448R2
Permitting static constexpr variables in constexpr functions 202211L (C++23) P2647R1
__cpp_constexpr_dynamic_alloc Operations for dynamic storage duration in constexpr functions 201907L (C++20) P0784R7
__cpp_constexpr_in_decltype Generation of function and variable definitions when needed for constant evaluation 201711L (C++11)
(DR)
P0859R0
__cpp_constinit constinit 201907L (C++20) P1143R2
__cpp_decltype decltype 200707L (C++11) N2343
__cpp_decltype_auto Return type deduction for normal functions 201304L (C++14) N3638
__cpp_deduction_guides Template argument deduction for class templates 201703L (C++17) P0091R3
P0512R0
P0620R0
CTAD for aggregates and aliases 201907L (C++20) P1814R0
P1816R0
__cpp_delegating_constructors Delegating constructors 200604L (C++11) N1986
__cpp_designated_initializers Designated initializer 201707L (C++20) P0329R4
__cpp_enumerator_attributes Attributes for enumerators 201411L (C++17) N4266
__cpp_explicit_this_parameter Explicit object parameter 202110L (C++23) P0847R7
__cpp_fold_expressions Fold expressions 201603L (C++17) N4295
P0036R0
__cpp_generic_lambdas Generic lambda expressions 201304L (C++14) N3649
Explicit template parameter list for generic lambdas 201707L (C++20) P0428R2
__cpp_guaranteed_copy_elision Guaranteed copy elision through simplified value categories 201606L (C++17) P0135R1
__cpp_hex_float Hexadecimal floating literals 201603L (C++17) P0245R1
__cpp_if_consteval consteval if 202106L (C++23) P1938R3
__cpp_if_constexpr constexpr if 201606L (C++17) P0292R2
__cpp_impl_coroutine Coroutines (compiler support) 201902L (C++20) P0912R5
LWG3393
__cpp_impl_destroying_delete Destroying operator delete (compiler support) 201806L (C++20) P0722R3
__cpp_impl_three_way_comparison Three-way comparison (compiler support) 201907L (C++20) P0515R3
P0768R1
P1185R2
P1630R1
__cpp_implicit_move Simpler implicit move 202207L (C++23) P2266R3
__cpp_inheriting_constructors Inheriting constructors 200802L (C++11) N2540
Rewording inheriting constructors 201511L (C++11)
(DR)
P0136R1
__cpp_init_captures Lambda init-capture 201304L (C++14) N3648
Allow pack expansion in lambda init-capture 201803L (C++20) P0780R2
__cpp_initializer_lists List-initialization and std::initializer_list 200806L (C++11) N2672
__cpp_inline_variables Inline variables 201606L (C++17) P0386R2
__cpp_lambdas Lambda expressions 200907L (C++11) N2927
__cpp_modules Modules 201907L (C++20) P1103R3
P1811R0
__cpp_multidimensional_subscript Multidimensional subscript operator 202110L (C++23) P2128R6
static operator[] 202211L (C++23) P2589R1
__cpp_named_character_escapes Named universal character escapes 202207L (C++23) P2071R2
__cpp_namespace_attributes Attributes for namespaces 201411L (C++17) N4266
__cpp_noexcept_function_type Make exception specifications be part of the type system 201510L (C++17) P0012R1
__cpp_nontype_template_args Allow constant evaluation for all non-type template arguments 201411L (C++17) N4268
Class types and floating-point types in non-type template parameters 201911L (C++20) P1907R1
__cpp_nontype_template_parameter_auto Declaring non-type template parameters with auto 201606L (C++17) P0127R2
__cpp_nsdmi Non-static data member initializers 200809L (C++11) N2756
__cpp_range_based_for Range-based for loop 200907L (C++11) N2930
Range-based for loop with different begin/end types 201603L (C++17) P0184R0
Lifetime extension in range-based for 202211L (C++23) P2718R0
__cpp_raw_strings Raw string literals 200710L (C++11) N2442
__cpp_ref_qualifiers ref-qualifiers 200710L (C++11) N2439
__cpp_return_type_deduction Return type deduction for normal functions 201304L (C++14) N3638
__cpp_rvalue_references Rvalue reference 200610L (C++11) N2118
__cpp_size_t_suffix Literal suffixes for size_t and its signed version 202011L (C++23) P0330R8
__cpp_sized_deallocation Sized deallocation 201309L (C++14) N3778
__cpp_static_assert static_assert 200410L (C++11) N1720
Single-argument static_assert 201411L (C++17) N3928
__cpp_static_call_operator static operator() 202207L (C++23) P1169R4
__cpp_structured_bindings Structured bindings 201606L (C++17) P0217R3
__cpp_template_template_args Matching of template template-arguments 201611L (C++17) P0522R0
__cpp_threadsafe_static_init Dynamic initialization and destruction with concurrency 200806L (C++11) N2660
__cpp_unicode_characters New character types (char16_t and char32_t) 200704L (C++11) N2249
__cpp_unicode_literals Unicode string literals 200710L (C++11) N2442
__cpp_user_defined_literals User-defined literals 200809L (C++11) N2765
__cpp_using_enum using enum 201907L (C++20) P1099R5
__cpp_variable_templates Variable templates 201304L (C++14) N3651
__cpp_variadic_templates Variadic templates 200704L (C++11) N2242
__cpp_variadic_using Pack expansions in using-declarations 201611L (C++17) P0195R2
Total number of macros: 66

Library features

The following macros are defined if the header <version> or any of the corresponding headers in the table below is included. Each macro expands to an integer literal corresponding to the year and month when the corresponding feature has been included in the working draft.

When a feature changes significantly, the macro will be updated accordingly.

Macro name Feature Value Header Std Paper(s)
__cpp_lib_adaptor_iterator_pair_constructor Iterator pair constructors for std::stack and std::queue 202106L <queue> <stack> (C++23) P1425R4
__cpp_lib_addressof_constexpr Constexpr std::addressof 201603L <memory> (C++17) LWG2296
__cpp_lib_algorithm_iterator_requirements Ranges iterators as inputs to non-Ranges algorithms 202207L <algorithm> <memory> <numeric> (C++23) P2408R5
__cpp_lib_allocate_at_least Size-feedback in the Allocator interface, e.g.: std::allocator::allocate_at_least, std::allocator_traits::allocate_at_least 202302L <memory> (C++23) P0401R6
P2652R2
__cpp_lib_allocator_traits_is_always_equal std::allocator_traits::is_always_equal 201411L <memory> <scoped_allocator> <string> <deque> <forward_list> <list> <vector> <map> <set> <unordered_map> <unordered_set> (C++17) N4258
__cpp_lib_any std::any 201606L <any> (C++17) P0220R1
P0032R3
__cpp_lib_apply std::apply 201603L <tuple> (C++17) P0220R1
__cpp_lib_array_constexpr Constexpr for std::reverse_iterator, std::move_iterator, std::array and range access 201603L <iterator> <array> (C++17) P0031R0
ConstexprIterator; constexpr comparison for std::array; misc constexpr bits (std::array::fill et al.) 201811L <iterator> <array> (C++20) P0858R0
LWG3257
P1023R0
P1032R1
__cpp_lib_as_const std::as_const 201510L <utility> (C++17) P0007R1
__cpp_lib_associative_heterogeneous_erasure Heterogeneous erasure in associative containers and unordered associative containers 202110L <map> <set> <unordered_map> <unordered_set> (C++23) P2077R3
__cpp_lib_assume_aligned std::assume_aligned 201811L <memory> (C++20) P1007R3
__cpp_lib_atomic_flag_test std::atomic_flag::test 201907L <atomic> (C++20) P1135R6
__cpp_lib_atomic_float Floating-point atomic 201711L <atomic> (C++20) P0020R6
__cpp_lib_atomic_is_always_lock_free constexpr atomic<T>::is_always_lock_free 201603L <atomic> (C++17) P0152R1
__cpp_lib_atomic_lock_free_type_aliases atomic lockfree integral types (std::atomic_signed_lock_free, std::atomic_unsigned_lock_free) 201907L <atomic> (C++20) P1135R6
__cpp_lib_atomic_ref std::atomic_ref 201806L <atomic> (C++20) P0019R8
__cpp_lib_atomic_shared_ptr std::atomic<std::shared_ptr> 201711L <memory> (C++20) P0718R2
__cpp_lib_atomic_value_initialization Fixing atomic initialization (value-initialize std::atomic by default) 201911L <atomic> <memory> (C++20) P0883R2
__cpp_lib_atomic_wait Efficient std::atomic waiting 201907L <atomic> (C++20) P1135R6
__cpp_lib_barrier std::barrier 201907L <barrier> (C++20) P1135R6
std::barrier's phase completion guarantees 202302L <barrier> (C++23) P2588R3
__cpp_lib_bind_back std::bind_back 202202L <functional> (C++23) P2387R3
__cpp_lib_bind_front std::bind_front 201907L <functional> (C++20) P0356R5
P1651R0
__cpp_lib_bit_cast std::bit_cast 201806L <bit> (C++20) P0476R2
__cpp_lib_bitops Bit operations 201907L <bit> (C++20) P0553R4
__cpp_lib_bool_constant std::bool_constant 201505L <type_traits> (C++17) N4389
__cpp_lib_bounded_array_traits std::is_bounded_array, std::is_unbounded_array 201902L <type_traits> (C++20) P1357R1
__cpp_lib_boyer_moore_searcher Searchers 201603L <functional> (C++17) P0220R1
__cpp_lib_byte std::byte 201603L <cstddef> (C++17) P0298R3
__cpp_lib_byteswap std::byteswap 202110L <bit> (C++23) P1272R4
__cpp_lib_char8_t Library support for char8_t 201907L <atomic> <filesystem> <istream> <limits> <locale> <ostream> <string> <string_view> (C++20) P0482R6
P1423R3
__cpp_lib_chrono Rounding functions for std::chrono::duration and std::chrono::time_point 201510L <chrono> (C++17) P0092R1
Constexpr for all the member functions of std::chrono::duration and std::chrono::time_point 201611L <chrono> (C++17) P0505R0
Calendars and Time Zones 201907L <chrono> (C++20) P0355R7
P1466R3
__cpp_lib_chrono_udls User-defined literals for time types 201304L <chrono> (C++14) N3642
__cpp_lib_clamp std::clamp 201603L <algorithm> (C++17) P0025R0
__cpp_lib_common_reference Make std::common_reference_t of std::reference_wrapper a reference type 202302L <type_traits> (C++23) P2655R3
__cpp_lib_common_reference_wrapper Make std::common_reference_t of std::reference_wrapper a reference type 202302L <functional> (C++23) P2655R3
__cpp_lib_complex_udls User-defined Literals for std::complex 201309L <complex> (C++14) N3779
__cpp_lib_concepts Standard library concepts 202002L <concepts> (C++20) P0898R3
P1754R1
P1964R2
Move-only types for equality_comparable_with, totally_ordered_with, and three_way_comparable_with 202207L <compare> <concepts> (C++23) P2404R3
__cpp_lib_constexpr_algorithms Constexpr for algorithms 201806L <algorithm> (C++20) P0202R3
P0879R0
LWG3256
Constexpr stable sorting 202306L? <algorithm> (C++26) P2562R1
__cpp_lib_constexpr_bitset A more constexpr std::bitset 202207L <bitset> (C++23) P2417R2
__cpp_lib_constexpr_charconv Add constexpr modifiers to functions std::to_chars and std::from_chars for integral types 202207L <charconv> (C++23) P2291R3
__cpp_lib_constexpr_cmath Constexpr for mathematical functions in <cmath> and <cstdlib> 202202L <cmath> <cstdlib> (C++23) P0533R9
__cpp_lib_constexpr_complex Constexpr for std::complex 201711L <complex> (C++20) P0415R1
__cpp_lib_constexpr_dynamic_alloc Constexpr for std::allocator and related utilities 201907L <memory> (C++20) P0784R7
__cpp_lib_constexpr_functional Misc constexpr bits (std::default_searcher); constexpr INVOKE 201907L <functional> (C++20) P1032R1
P1065R2
__cpp_lib_constexpr_iterator Misc constexpr bits (std::insert_iterator et al.) 201811L <iterator> (C++20) P1032R1
__cpp_lib_constexpr_memory Constexpr in std::pointer_traits 201811L <memory> (C++20) P1006R1
Constexpr std::unique_ptr 202202L <memory> (C++23) P2273R3
__cpp_lib_constexpr_numeric Constexpr for algorithms in <numeric> 201911L <numeric> (C++20) P1645R1
__cpp_lib_constexpr_string Constexpr for std::string 201907L <string> (C++20) P0426R1
P1032R1
P0980R1
__cpp_lib_constexpr_string_view Misc constexpr bits (std::string_view::copy) 201811L <string_view> (C++20) P0426R1
P1032R1
__cpp_lib_constexpr_tuple Misc constexpr bits (std::tuple::operator= et al.) 201811L <tuple> (C++20) P1032R1
__cpp_lib_constexpr_typeinfo Constexpr for std::type_info::operator== 202106L <typeinfo> (C++23) P1328R1
__cpp_lib_constexpr_utility Misc constexpr bits (std::pair::operator= et al.) 201811L <utility> (C++20) P1032R1
__cpp_lib_constexpr_vector Constexpr for std::vector 201907L <vector> (C++20) P1004R2
__cpp_lib_containers_ranges Ranges-aware construction and insertion for containers and strings 202202L <vector> <list> <forward_list> <map> <set> <unordered_map> <unordered_set> <deque> <queue> <stack> <string> (C++23) P1206R7
__cpp_lib_coroutine Coroutines (library support) 201902L <coroutine> (C++20) P0912R5
LWG3393
__cpp_lib_destroying_delete Destroying operator delete (library support) 201806L <new> (C++20) P0722R3
__cpp_lib_enable_shared_from_this std::enable_shared_from_this::weak_from_this 201603L <memory> (C++17) P0033R1
__cpp_lib_endian std::endian 201907L <bit> (C++20) P0463R1
P1612R1
__cpp_lib_erase_if Uniform container erasure 202002L <string> <deque> <forward_list> <list> <vector> <map> <set> <unordered_map> <unordered_set> (C++20) P1209R0
P1115R3
__cpp_lib_exchange_function std::exchange 201304L <utility> (C++14) N3668
__cpp_lib_execution Execution policies 201603L <execution> (C++17) P0024R2
std::execution::unsequenced_policy 201902L <execution> (C++20) P1001R2
__cpp_lib_expected class template std::expected 202202L <expected> (C++23) P0323R12
Monadic functions for std::expected 202211L <expected> (C++23) P2505R5
__cpp_lib_filesystem Filesystem library 201703L <filesystem> (C++17) P0218R1
P0219R1
P0392R0
P0317R1
__cpp_lib_flat_map std::flat_map and std::flat_multimap 202207L <flat_map> (C++23) P0429R9
__cpp_lib_flat_set std::flat_set and std::flat_multiset 202207L <flat_set> (C++23) P1222R4
LWG3751
__cpp_lib_format Text formatting 201907L <format> (C++20) P0645R10
P1361R2
P1652R1
Compile-time format string checks; Reducing parameterization of std::vformat_to 202106L <format> (C++20)
(DR)
P2216R3
Fixing locale handling in chrono formatters; Supporting non-const-formattable types 202110L <format> (C++20)
(DR)
P2372R3
P2418R2
Exposing std::basic_format_string; clarify handling of encodings in localized formatting of chrono types 202207L <format> (C++23) P2419R2
P2508R1
__cpp_lib_format_ranges Formatting ranges 202207L <format> (C++23) P2286R8
P2585R1
LWG3750
__cpp_lib_formatters Formatting std::thread::id and std::stacktrace 202302L <stacktrace> <thread> (C++23) P2693R1
__cpp_lib_forward_like std::forward_like 202207L <utility> (C++23) P2445R1
__cpp_lib_gcd_lcm std::gcd, std::lcm 201606L <numeric> (C++17) P0295R0
__cpp_lib_generator std::generator: synchronous coroutine generator for ranges 202207L <generator> (C++23) P2502R2
__cpp_lib_generic_associative_lookup Heterogeneous comparison lookup in associative containers 201304L <map> <set> (C++14) N3657
__cpp_lib_generic_unordered_lookup Heterogeneous comparison lookup in unordered associative containers 201811L <unordered_map> <unordered_set> (C++20) P0919R3
__cpp_lib_hardware_interference_size constexpr std::hardware_{constructive, destructive}_interference_size 201703L <new> (C++17) P0154R1
__cpp_lib_has_unique_object_representations std::has_unique_object_representations 201606L <type_traits> (C++17) P0258R2
__cpp_lib_hypot 3-argument overload of std::hypot 201603L <cmath> (C++17) P0030R1
__cpp_lib_incomplete_container_elements Minimal incomplete type support for std::forward_list, std::list, and std::vector 201505L <forward_list> <list> <vector> (C++17) N4510
__cpp_lib_int_pow2 Integral power-of-2 operations (std::has_single_bit, std::bit_ceil, std::bit_floor, std::bit_width) 202002L <bit> (C++20) P0556R3
P1956R1
__cpp_lib_integer_comparison_functions Integer comparison functions 202002L <utility> (C++20) P0586R2
__cpp_lib_integer_sequence Compile-time integer sequences 201304L <utility> (C++14) N3658
__cpp_lib_integral_constant_callable std::integral_constant::operator() 201304L <type_traits> (C++14) N3545
__cpp_lib_interpolate std::lerp, std::midpoint 201902L <cmath> <numeric> (C++20) P0811R3
__cpp_lib_invoke std::invoke 201411L <functional> (C++17) N4169
__cpp_lib_invoke_r std::invoke_r 202106L <functional> (C++23) P2136R3
__cpp_lib_ios_noreplace Support exclusive mode for fstreams 202207L <ios> (C++23) P2467R1
__cpp_lib_is_aggregate std::is_aggregate 201703L <type_traits> (C++17) LWG2911
__cpp_lib_is_constant_evaluated std::is_constant_evaluated 201811L <type_traits> (C++20) P0595R2
__cpp_lib_is_final std::is_final 201402L <type_traits> (C++14) LWG2112
__cpp_lib_is_implicit_lifetime std::is_implicit_lifetime 202302L <type_traits> (C++23) P2674R1
__cpp_lib_is_invocable std::is_invocable, std::invoke_result 201703L <type_traits> (C++17) P0604R0
__cpp_lib_is_layout_compatible std::is_layout_compatible 201907L <type_traits> (C++20) P0466R5
__cpp_lib_is_nothrow_convertible std::is_nothrow_convertible 201806L <type_traits> (C++20) P0758R1
LWG3356
__cpp_lib_is_null_pointer std::is_null_pointer 201309L <type_traits> (C++14) LWG2247
__cpp_lib_is_pointer_interconvertible Pointer-interconvertibility traits: std::is_pointer_interconvertible_with_class, std::is_pointer_interconvertible_base_of 201907L <type_traits> (C++20) P0466R5
__cpp_lib_is_scoped_enum std::is_scoped_enum 202011L <type_traits> (C++23) P1048R1
__cpp_lib_is_swappable [nothrow-]swappable traits 201603L <type_traits> (C++17) P0185R1
__cpp_lib_jthread Stop token and joining thread 201911L <stop_token> <thread> (C++20) P0660R10
P1869R1
__cpp_lib_latch std::latch 201907L <latch> (C++20) P1135R6
__cpp_lib_launder Core Issue 1776: Replacement of class objects containing reference members (std::launder) 201606L <new> (C++17) P0137R1
__cpp_lib_list_remove_return_type Change the return type of the remove(), remove_if() and unique() members of std::forward_list and std::list 201806L <forward_list> <list> (C++20) P0646R1
__cpp_lib_logical_traits Logical operations on type traits 201510L <type_traits> (C++17) P0013R1
__cpp_lib_make_from_tuple std::make_from_tuple() 201606L <tuple> (C++17) P0209R2
__cpp_lib_make_reverse_iterator std::make_reverse_iterator 201402L <iterator> (C++14) LWG2285
__cpp_lib_make_unique std::make_unique 201304L <memory> (C++14) N3656
__cpp_lib_map_try_emplace std::map::try_emplace, std::map::insert_or_assign 201411L <map> (C++17) N4279
__cpp_lib_math_constants Mathematical constants 201907L <numbers> (C++20) P0631R8
__cpp_lib_math_special_functions Mathematical special functions for C++17 201603L <cmath> (C++17) P0226R1
__cpp_lib_mdspan std::mdspan 202207L <mdspan> (C++23) P0009R18
P2599R2
P2604R0
P2613R1
__cpp_lib_memory_resource std::pmr::memory_resource 201603L <memory_resource> (C++17) P0220R1
__cpp_lib_modules Standard library modules std and std.compat 202207L (C++23) P2465R3
__cpp_lib_move_iterator_concept Make std::move_iterator<T*> a random access iterator 202207L <iterator> (C++23) P2520R0
__cpp_lib_move_only_function std::move_only_function 202110L <functional> (C++23) P0288R9
__cpp_lib_node_extract Splicing maps and sets (std::map::extract, std::map::merge, std::map::insert(node_type), etc) 201606L <map> <set> <unordered_map> <unordered_set> (C++17) P0083R3
__cpp_lib_nonmember_container_access std::size(), std::data() and std::empty() 201411L <iterator> <array> <deque> <forward_list> <list> <map> <regex> <set> <string> <unordered_map> <unordered_set> <vector> (C++17) N4280
__cpp_lib_not_fn std::not_fn() 201603L <functional> (C++17) P0005R4
__cpp_lib_null_iterators Null LegacyForwardIterators 201304L <iterator> (C++14) N3644
__cpp_lib_optional std::optional 201606L <optional> (C++17) P0220R1
P0032R3
P0307R2
Fully constexpr std::optional 202106L <optional> (C++20)
(DR)
P2231R1
Monadic operations in std::optional 202110L <optional> (C++23) P0798R8
LWG3621
__cpp_lib_out_ptr std::out_ptr, std::inout_ptr 202106L <memory> (C++23) P1132R7
__cpp_lib_parallel_algorithm Parallel algorithms 201603L <algorithm> <numeric> (C++17) P0024R2
__cpp_lib_polymorphic_allocator std::pmr::polymorphic_allocator<> as a vocabulary type 201902L <memory_resource> (C++20) P0339R6
LWG3437
__cpp_lib_print Formatted output 202207L <ostream> <print> (C++23) P2093R14
__cpp_lib_quoted_string_io std::quoted 201304L <iomanip> (C++14) N3654
__cpp_lib_ranges Ranges library and constrained algorithms 201911L <algorithm> <functional> <iterator> <memory> <ranges> (C++20) P0896R4
P1035R7
P1716R3
Non-default-initializable views 202106L (C++20)
(DR)
P2325R3
Views with ownership 202110L (C++20)
(DR)
P2415R2
std::ranges::range_adaptor_closure 202202L (C++23) P2387R3
Relaxing range adaptors to allow for move-only types 202207L (C++23) P2494R2
Removing 'poison pill' overloads in ranges::begin, ranges::end, ranges::rbegin, ranges::rend, and ranges::size 202211L (C++23) P2602R2
Relaxing ranges to allow certain projections 202302L (C++23) P2609R3
__cpp_lib_ranges_as_const std::const_iterator, std::ranges::as_const_view 202207L <ranges> (C++23) P2278R4
__cpp_lib_ranges_as_rvalue std::ranges::as_rvalue_view 202207L <ranges> (C++23) P2446R2
__cpp_lib_ranges_cartesian_product std::ranges::cartesian_product_view 202207L <ranges> (C++23) P2374R4
P2540R1
__cpp_lib_ranges_chunk std::ranges::chunk_view 202202L <ranges> (C++23) P2442R1
__cpp_lib_ranges_chunk_by std::ranges::chunk_by_view 202202L <ranges> (C++23) P2443R1
__cpp_lib_ranges_contains std::ranges::contains 202207L <algorithm> (C++23) P2302R4
__cpp_lib_ranges_enumerate std::ranges::enumerate_view 202302L <ranges> (C++23) P2164R9
__cpp_lib_ranges_find_last std::find_last(), std::find_last(), and std::find_last() 202207L <algorithm> (C++23) P1223R5
__cpp_lib_ranges_fold std::ranges fold algorithms 202207L <algorithm> (C++23) P2322R6
__cpp_lib_ranges_iota std::ranges::iota 202202L <numeric> (C++23) P2440R1
__cpp_lib_ranges_join_with std::ranges::join_with_view 202202L <ranges> (C++23) P2441R2
__cpp_lib_ranges_repeat std::ranges::repeat_view 202207L <ranges> (C++23) P2474R2
__cpp_lib_ranges_slide std::ranges::slide_view 202202L <ranges> (C++23) P2442R1
__cpp_lib_ranges_starts_ends_with std::ranges::starts_with, std::ranges::ends_with 202106L <algorithm> (C++23) P1659R3
__cpp_lib_ranges_stride std::ranges::stride_view 202207L <ranges> (C++23) P1899R3
__cpp_lib_ranges_to_container std::ranges::to 202202L <ranges> (C++23) P1206R7
__cpp_lib_ranges_zip std::ranges::zip_view, std::ranges::zip_transform_view, std::ranges::adjacent_view, std::ranges::adjacent_transform_view 202110L <ranges> <tuple> <utility> (C++23) P2321R2
__cpp_lib_raw_memory_algorithms Extending memory management tools 201606L <memory> (C++17) P0040R3
__cpp_lib_reference_from_temporary std::reference_constructs_from_temporary and std::reference_converts_from_temporary 202202L <type_traits> (C++23) P2255R2
__cpp_lib_remove_cvref std::remove_cvref 201711L <type_traits> (C++20) P0550R2
__cpp_lib_result_of_sfinae std::result_of and SFINAE 201210L <type_traits> <functional> (C++14) N3462
__cpp_lib_robust_nonmodifying_seq_ops Making non-modifying sequence operations more robust (two-range overloads for std::mismatch, std::equal and std::is_permutation) 201304L <algorithm> (C++14) N3671
__cpp_lib_sample std::sample 201603L <algorithm> (C++17) P0220R1
__cpp_lib_scoped_lock std::scoped_lock 201703L <mutex> (C++17) P0156R2
__cpp_lib_semaphore std::counting_semaphore, std::binary_semaphore 201907L <semaphore> (C++20) P1135R6
__cpp_lib_shared_mutex std::shared_mutex (untimed) 201505L <shared_mutex> (C++17) N4508
__cpp_lib_shared_ptr_arrays std::shared_ptr<T[]> 201611L <memory> (C++17) P0497R0
Array support of std::make_shared 201707L <memory> (C++20) P0674R1
__cpp_lib_shared_ptr_weak_type shared_ptr::weak_type 201606L <memory> (C++17) P0163R0
__cpp_lib_shared_timed_mutex std::shared_timed_mutex 201402L <shared_mutex> (C++14) N3891
__cpp_lib_shift std::shift_left and std::shift_right 201806L <algorithm> (C++20) P0769R2
std::ranges::shift_left and std::ranges::shift_right 202202L <algorithm> (C++23) P2440R1
__cpp_lib_smart_ptr_for_overwrite Smart pointer creation with default initialization (std::allocate_shared_for_overwrite, std::make_shared_for_overwrite, std::make_unique_for_overwrite) 202002L <memory> (C++20) P1020R1
P1973R1
__cpp_lib_source_location Source-code information capture (std::source_location) 201907L <source_location> (C++20) P1208R6
__cpp_lib_span std::span 202002L <span> (C++20) P0122R7
LWG3274
P1024R3
P1976R2
__cpp_lib_spanstream std::spanbuf, std::spanstream 202106L <spanstream> (C++23) P0448R4
__cpp_lib_ssize std::ssize and unsigned std::span::size 201902L <iterator> (C++20) P1227R2
__cpp_lib_stacktrace Stacktrace library 202011L <stacktrace> (C++23) P0881R7
__cpp_lib_start_lifetime_as Explicit lifetime management (std::start_lifetime_as) 202207L <memory> (C++23) P2590R2
__cpp_lib_starts_ends_with String prefix and suffix checking (starts_with() and ends_with() for std::string and std::string_view) 201711L <string> <string_view> (C++20) P0457R2
__cpp_lib_stdatomic_h Compatibility header for C atomic operations 202011L <stdatomic.h> (C++23) P0943R6
__cpp_lib_string_contains contains functions of std::basic_string and std::basic_string_view 202011L <string> <string_view> (C++23) P1679R3
__cpp_lib_string_resize_and_overwrite std::basic_string::resize_and_overwrite 202110L <string> (C++23) P1072R10
__cpp_lib_string_udls User-defined literals for string types 201304L <string> (C++14) N3642
__cpp_lib_string_view std::string_view 201606L <string> <string_view> (C++17) P0220R1
P0254R2
ConstexprIterator 201803L <string> <string_view> (C++20) P0858R0
LWG3257
__cpp_lib_syncbuf Synchronized buffered ostream (std::syncbuf, std::osyncstream) and manipulators 201803L <syncstream> (C++20) P0053R7
P0753R2
__cpp_lib_three_way_comparison Three-way comparison (library support); adding three-way comparison to the library 201907L <compare> (C++20) P0768R1
P1614R2
__cpp_lib_to_address Utility to convert a pointer to a raw pointer (std::to_address) 201711L <memory> (C++20) P0653R2
__cpp_lib_to_array std::to_array 201907L <array> (C++20) P0325R4
__cpp_lib_to_chars Elementary string conversions (std::to_chars, std::from_chars) 201611L <charconv> (C++17) P0067R5
P0682R1
LWG3137
__cpp_lib_to_underlying std::to_underlying 202102L <utility> (C++23) P1682R2
__cpp_lib_transformation_trait_aliases Alias templates for TransformationTraits 201304L <type_traits> (C++14) N3655
__cpp_lib_transparent_operators Transparent operator functors (std::less<> et al) 201210L <functional> (C++14) N3421
Transparent std::owner_less (std::owner_less<void>) 201510L <memory> <functional> (C++17) P0074R0
__cpp_lib_tuple_element_t std::tuple_element_t 201402L <tuple> (C++14) N3887
__cpp_lib_tuple_like Compatibility between std::tuple and tuple-like objects (std::pair, std::array, std::subrange) 202207L <map> <tuple> <unordered_map> <utility> (C++23) P2165R4
__cpp_lib_tuples_by_type Addressing tuples by type 201304L <tuple> <utility> (C++14) N3670
__cpp_lib_type_identity std::type_identity 201806L <type_traits> (C++20) P0887R1
__cpp_lib_type_trait_variable_templates Type traits variable templates (std::is_void_v, etc) 201510L <type_traits> (C++17) P0006R0
__cpp_lib_uncaught_exceptions std::uncaught_exceptions 201411L <exception> (C++17) N4259
__cpp_lib_unordered_map_try_emplace std::unordered_map::try_emplace, std::unordered_map::insert_or_assign 201411L <unordered_map> (C++17) N4279
__cpp_lib_unreachable std::unreachable 202202L <utility> (C++23) P0627R6
__cpp_lib_unwrap_ref std::unwrap_ref_decay and std::unwrap_reference 201811L <type_traits> (C++20) P0318R1
LWG3348
__cpp_lib_variant std::variant: a type-safe union for C++17 201606L <variant> (C++17) P0088R3
P0393R3
P0032R3
std::visit for classes derived from std::variant 202102L <variant> (C++17)
(DR)
P2162R2
Fully constexpr std::variant 202106L <variant> (C++20)
(DR)
P2231R1
__cpp_lib_void_t std::void_t 201411L <type_traits> (C++17) N3911
Total number of macros: 185

Example

Normal usage

#ifdef __has_include                           // Check if __has_include is present
#  if __has_include(<optional>)                // Check for a standard library
#    include <optional>
#  elif __has_include(<experimental/optional>) // Check for an experimental version
#    include <experimental/optional>
#  elif __has_include(<boost/optional.hpp>)    // Try with an external library
#    include <boost/optional.hpp>
#  else                                        // Not found at all
#     error "Missing <optional>"
#  endif
#endif
 
#ifdef __has_cpp_attribute                      // Check if __has_cpp_attribute is present
#  if __has_cpp_attribute(deprecated)           // Check for an attribute
#    define DEPRECATED(msg) [[deprecated(msg)]]
#  endif
#endif
#ifndef DEPRECATED
#    define DEPRECATED(msg)
#endif
 
DEPRECATED("foo() has been deprecated") void foo();
 
#if __cpp_constexpr >= 201304                // Check for a specific version of a feature
#  define CONSTEXPR constexpr
#else
#  define CONSTEXPR inline
#endif
 
CONSTEXPR int bar(unsigned i)
{
#if __cpp_binary_literals                    // Check for the presence of a feature
    unsigned mask1 = 0b11000000;
    unsigned mask2 = 0b00000111;
#else
    unsigned mask1 = 0xC0;
    unsigned mask2 = 0x07;
#endif
    if ( i & mask1 )
        return 1;
    if ( i & mask2 )
        return 2;
    return 0;
}
 
int main()
{
}

Compiler Features Dump

The following (C++11 compatible) program dumps C++ compiler features and attributes.

static constexpr struct change_these_options_to_select_what_will_be_printed
{
    constexpr static int longest_macro_name { 44 };
    constexpr static bool titles               = 1;
    constexpr static bool counters             = 1;
    constexpr static bool attributes           = 1;
    constexpr static bool standard_values      = 1;
    constexpr static bool compiler_specific    = 1;
    constexpr static bool core_features        = 1;
    constexpr static bool lib_features         = 1;
    constexpr static bool supported_features   = 1;
    constexpr static bool unsupported_features = 1;
    constexpr static bool sort_by_date         = 0;
    constexpr static bool separate_year_month  = 1;
    constexpr static bool separated_revisions  = 1;
    constexpr static bool latest_revisions     = 1;
    constexpr static bool cxx98                = 0;
    constexpr static bool cxx11                = 1;
    constexpr static bool cxx14                = 1;
    constexpr static bool cxx17                = 1;
    constexpr static bool cxx20                = 1;
    constexpr static bool cxx23                = 1;
    constexpr static bool cxx26                = 0;
    constexpr static bool cxx29                = 0;
} print;
 
#if __cplusplus < 201100
#  error "C++11 or better is required"
#endif
 
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <utility>
#include <vector>
 
#ifdef __has_include
# if __has_include(<version>)
#   include <version>
# endif
#endif
 
// Expect a string that starts with 6-decimal-digits or with '_' (if unsupported)
#define COMPILER_VALUE_INT(n) #n [0] == '_' ? 0 : \
    (#n[5] - '0') + (#n[4] - '0') * 10 + (#n[3] - '0') * 100 + \
    (#n[2] - '0') * 1000 + (#n[1] - '0') * 10000 + (#n[0] - '0') * 100000
#define COMPILER_FEATURE_ENTRY(expect, name) { #name, COMPILER_VALUE_INT(name), expect },
 
#ifdef __has_cpp_attribute
# define COMPILER_ATTRIBUTE(expect, name) { #name, __has_cpp_attribute(name), expect },
#else
# define COMPILER_ATTRIBUTE(expect, name) { #name, COMPILER_VALUE_INT(name), expect },
#endif
 
#define COMPILER_SPECIFIC_STRING(value) #value
#define COMPILER_SPECIFIC_ENTRY(name) { #name, COMPILER_SPECIFIC_STRING(name) },
 
class CompilerFeature
{
    char const* name_; long data_; long std_;
public:
    constexpr CompilerFeature(char const* name, long data, long std)
        : name_(name), data_(data), std_(std) {}
    constexpr CompilerFeature(CompilerFeature const&) = default;
    CompilerFeature& operator=(CompilerFeature const&) = default;
    bool operator<(CompilerFeature const& rhs) const
        { return std::strcmp(name_, rhs.name_) < 0; }
    bool operator==(CompilerFeature const& rhs) const
        { return std::strcmp(name_, rhs.name_) == 0; }
    constexpr bool supported() const { return data_ >= std_; }
    constexpr bool maybe() const { return data_ > 0; }
    constexpr char const* name() const { return name_; }
    constexpr long std() const { return std_; }
    constexpr long data() const { return data_; }
    void data(long x) { data_ = x; }
};
 
static /*constexpr*/ std::pair<const char*, const char*> compiler[] = {
    COMPILER_SPECIFIC_ENTRY(__cplusplus) //< not compiler specific, but useful :)
    COMPILER_SPECIFIC_ENTRY(__clang_major__)
    COMPILER_SPECIFIC_ENTRY(__clang_minor__)
    COMPILER_SPECIFIC_ENTRY(__clang_patchlevel__)
    COMPILER_SPECIFIC_ENTRY(__GNUG__)
    COMPILER_SPECIFIC_ENTRY(__GNUC_MINOR__)
    COMPILER_SPECIFIC_ENTRY(__GNUC_PATCHLEVEL__)
    // Add your favorite compiler specific macros. Undefined ones will not be printed.
};
 
static constexpr CompilerFeature cxx98_core[] = {
    COMPILER_FEATURE_ENTRY(199711L, __cpp_exceptions)
    COMPILER_FEATURE_ENTRY(199711L, __cpp_rtti)
};
 
static constexpr CompilerFeature cxx11_core[] = {
    COMPILER_FEATURE_ENTRY(200704L, __cpp_alias_templates)
    COMPILER_FEATURE_ENTRY(200809L, __cpp_attributes)
    COMPILER_FEATURE_ENTRY(200704L, __cpp_constexpr)
    COMPILER_FEATURE_ENTRY(201711L, __cpp_constexpr_in_decltype)
    COMPILER_FEATURE_ENTRY(200707L, __cpp_decltype)
    COMPILER_FEATURE_ENTRY(200604L, __cpp_delegating_constructors)
    COMPILER_FEATURE_ENTRY(201511L, __cpp_inheriting_constructors)
    COMPILER_FEATURE_ENTRY(200806L, __cpp_initializer_lists)
    COMPILER_FEATURE_ENTRY(200907L, __cpp_lambdas)
    COMPILER_FEATURE_ENTRY(200809L, __cpp_nsdmi)
    COMPILER_FEATURE_ENTRY(200907L, __cpp_range_based_for)
    COMPILER_FEATURE_ENTRY(200710L, __cpp_raw_strings)
    COMPILER_FEATURE_ENTRY(200710L, __cpp_ref_qualifiers)
    COMPILER_FEATURE_ENTRY(200610L, __cpp_rvalue_references)
    COMPILER_FEATURE_ENTRY(200410L, __cpp_static_assert)
    COMPILER_FEATURE_ENTRY(200806L, __cpp_threadsafe_static_init)
    COMPILER_FEATURE_ENTRY(200704L, __cpp_unicode_characters)
    COMPILER_FEATURE_ENTRY(200710L, __cpp_unicode_literals)
    COMPILER_FEATURE_ENTRY(200809L, __cpp_user_defined_literals)
    COMPILER_FEATURE_ENTRY(200704L, __cpp_variadic_templates)
};
 
static constexpr CompilerFeature cxx14_core[] = {
    COMPILER_FEATURE_ENTRY(201304L, __cpp_aggregate_nsdmi)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_binary_literals)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_constexpr)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_decltype_auto)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_generic_lambdas)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_init_captures)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_return_type_deduction)
    COMPILER_FEATURE_ENTRY(201309L, __cpp_sized_deallocation)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_variable_templates)
};
static constexpr CompilerFeature cxx14_lib[] = {
    COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_chrono_udls)
    COMPILER_FEATURE_ENTRY(201309L, __cpp_lib_complex_udls)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_exchange_function)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_generic_associative_lookup)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_integer_sequence)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_integral_constant_callable)
    COMPILER_FEATURE_ENTRY(201402L, __cpp_lib_is_final)
    COMPILER_FEATURE_ENTRY(201309L, __cpp_lib_is_null_pointer)
    COMPILER_FEATURE_ENTRY(201402L, __cpp_lib_make_reverse_iterator)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_make_unique)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_null_iterators)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_quoted_string_io)
    COMPILER_FEATURE_ENTRY(201210L, __cpp_lib_result_of_sfinae)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_robust_nonmodifying_seq_ops)
    COMPILER_FEATURE_ENTRY(201402L, __cpp_lib_shared_timed_mutex)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_string_udls)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_transformation_trait_aliases)
    COMPILER_FEATURE_ENTRY(201210L, __cpp_lib_transparent_operators)
    COMPILER_FEATURE_ENTRY(201402L, __cpp_lib_tuple_element_t)
    COMPILER_FEATURE_ENTRY(201304L, __cpp_lib_tuples_by_type)
};
 
static constexpr CompilerFeature cxx17_core[] = {
    COMPILER_FEATURE_ENTRY(201603L, __cpp_aggregate_bases)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_aligned_new)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_capture_star_this)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_constexpr)
    COMPILER_FEATURE_ENTRY(201703L, __cpp_deduction_guides)
    COMPILER_FEATURE_ENTRY(201411L, __cpp_enumerator_attributes)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_fold_expressions)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_guaranteed_copy_elision)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_hex_float)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_if_constexpr)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_inline_variables)
    COMPILER_FEATURE_ENTRY(201411L, __cpp_namespace_attributes)
    COMPILER_FEATURE_ENTRY(201510L, __cpp_noexcept_function_type)
    COMPILER_FEATURE_ENTRY(201411L, __cpp_nontype_template_args)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_nontype_template_parameter_auto)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_range_based_for)
    COMPILER_FEATURE_ENTRY(201411L, __cpp_static_assert)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_structured_bindings)
    COMPILER_FEATURE_ENTRY(201611L, __cpp_template_template_args)
    COMPILER_FEATURE_ENTRY(201611L, __cpp_variadic_using)
};
static constexpr CompilerFeature cxx17_lib[] = {
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_addressof_constexpr)
    COMPILER_FEATURE_ENTRY(201411L, __cpp_lib_allocator_traits_is_always_equal)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_any)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_apply)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_array_constexpr)
    COMPILER_FEATURE_ENTRY(201510L, __cpp_lib_as_const)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_atomic_is_always_lock_free)
    COMPILER_FEATURE_ENTRY(201505L, __cpp_lib_bool_constant)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_boyer_moore_searcher)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_byte)
    COMPILER_FEATURE_ENTRY(201611L, __cpp_lib_chrono)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_clamp)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_enable_shared_from_this)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_execution)
    COMPILER_FEATURE_ENTRY(201703L, __cpp_lib_filesystem)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_gcd_lcm)
    COMPILER_FEATURE_ENTRY(201703L, __cpp_lib_hardware_interference_size)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_has_unique_object_representations)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_hypot)
    COMPILER_FEATURE_ENTRY(201505L, __cpp_lib_incomplete_container_elements)
    COMPILER_FEATURE_ENTRY(201411L, __cpp_lib_invoke)
    COMPILER_FEATURE_ENTRY(201703L, __cpp_lib_is_aggregate)
    COMPILER_FEATURE_ENTRY(201703L, __cpp_lib_is_invocable)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_is_swappable)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_launder)
    COMPILER_FEATURE_ENTRY(201510L, __cpp_lib_logical_traits)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_make_from_tuple)
    COMPILER_FEATURE_ENTRY(201411L, __cpp_lib_map_try_emplace)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_math_special_functions)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_memory_resource)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_node_extract)
    COMPILER_FEATURE_ENTRY(201411L, __cpp_lib_nonmember_container_access)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_not_fn)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_optional)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_parallel_algorithm)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_raw_memory_algorithms)
    COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_sample)
    COMPILER_FEATURE_ENTRY(201703L, __cpp_lib_scoped_lock)
    COMPILER_FEATURE_ENTRY(201505L, __cpp_lib_shared_mutex)
    COMPILER_FEATURE_ENTRY(201611L, __cpp_lib_shared_ptr_arrays)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_shared_ptr_weak_type)
    COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_string_view)
    COMPILER_FEATURE_ENTRY(201611L, __cpp_lib_to_chars)
    COMPILER_FEATURE_ENTRY(201510L, __cpp_lib_transparent_operators)
    COMPILER_FEATURE_ENTRY(201510L, __cpp_lib_type_trait_variable_templates)
    COMPILER_FEATURE_ENTRY(201411L, __cpp_lib_uncaught_exceptions)
    COMPILER_FEATURE_ENTRY(201411L, __cpp_lib_unordered_map_try_emplace)
    COMPILER_FEATURE_ENTRY(202102L, __cpp_lib_variant)
    COMPILER_FEATURE_ENTRY(201411L, __cpp_lib_void_t)
};
 
static constexpr CompilerFeature cxx20_core[] = {
    COMPILER_FEATURE_ENTRY(201902L, __cpp_aggregate_paren_init)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_char8_t)
    COMPILER_FEATURE_ENTRY(202002L, __cpp_concepts)
    COMPILER_FEATURE_ENTRY(201806L, __cpp_conditional_explicit)
    COMPILER_FEATURE_ENTRY(202211L, __cpp_consteval)
    COMPILER_FEATURE_ENTRY(202002L, __cpp_constexpr)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_constexpr_dynamic_alloc)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_constinit)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_deduction_guides)
    COMPILER_FEATURE_ENTRY(201707L, __cpp_designated_initializers)
    COMPILER_FEATURE_ENTRY(201707L, __cpp_generic_lambdas)
    COMPILER_FEATURE_ENTRY(201902L, __cpp_impl_coroutine)
    COMPILER_FEATURE_ENTRY(201806L, __cpp_impl_destroying_delete)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_impl_three_way_comparison)
    COMPILER_FEATURE_ENTRY(201803L, __cpp_init_captures)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_modules)
    COMPILER_FEATURE_ENTRY(201911L, __cpp_nontype_template_args)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_using_enum)
};
static constexpr CompilerFeature cxx20_lib[] = {
    COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_array_constexpr)
    COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_assume_aligned)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_atomic_flag_test)
    COMPILER_FEATURE_ENTRY(201711L, __cpp_lib_atomic_float)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_atomic_lock_free_type_aliases)
    COMPILER_FEATURE_ENTRY(201806L, __cpp_lib_atomic_ref)
    COMPILER_FEATURE_ENTRY(201711L, __cpp_lib_atomic_shared_ptr)
    COMPILER_FEATURE_ENTRY(201911L, __cpp_lib_atomic_value_initialization)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_atomic_wait)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_barrier)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_bind_front)
    COMPILER_FEATURE_ENTRY(201806L, __cpp_lib_bit_cast)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_bitops)
    COMPILER_FEATURE_ENTRY(201902L, __cpp_lib_bounded_array_traits)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_char8_t)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_chrono)
    COMPILER_FEATURE_ENTRY(202002L, __cpp_lib_concepts)
    COMPILER_FEATURE_ENTRY(201806L, __cpp_lib_constexpr_algorithms)
    COMPILER_FEATURE_ENTRY(201711L, __cpp_lib_constexpr_complex)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_constexpr_dynamic_alloc)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_constexpr_functional)
    COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_constexpr_iterator)
    COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_constexpr_memory)
    COMPILER_FEATURE_ENTRY(201911L, __cpp_lib_constexpr_numeric)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_constexpr_string)
    COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_constexpr_string_view)
    COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_constexpr_tuple)
    COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_constexpr_utility)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_constexpr_vector)
    COMPILER_FEATURE_ENTRY(201902L, __cpp_lib_coroutine)
    COMPILER_FEATURE_ENTRY(201806L, __cpp_lib_destroying_delete)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_endian)
    COMPILER_FEATURE_ENTRY(202002L, __cpp_lib_erase_if)
    COMPILER_FEATURE_ENTRY(201902L, __cpp_lib_execution)
    COMPILER_FEATURE_ENTRY(202110L, __cpp_lib_format)
    COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_generic_unordered_lookup)
    COMPILER_FEATURE_ENTRY(202002L, __cpp_lib_int_pow2)
    COMPILER_FEATURE_ENTRY(202002L, __cpp_lib_integer_comparison_functions)
    COMPILER_FEATURE_ENTRY(201902L, __cpp_lib_interpolate)
    COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_is_constant_evaluated)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_is_layout_compatible)
    COMPILER_FEATURE_ENTRY(201806L, __cpp_lib_is_nothrow_convertible)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_is_pointer_interconvertible)
    COMPILER_FEATURE_ENTRY(201911L, __cpp_lib_jthread)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_latch)
    COMPILER_FEATURE_ENTRY(201806L, __cpp_lib_list_remove_return_type)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_math_constants)
    COMPILER_FEATURE_ENTRY(202106L, __cpp_lib_optional)
    COMPILER_FEATURE_ENTRY(201902L, __cpp_lib_polymorphic_allocator)
    COMPILER_FEATURE_ENTRY(202110L, __cpp_lib_ranges)
    COMPILER_FEATURE_ENTRY(201711L, __cpp_lib_remove_cvref)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_semaphore)
    COMPILER_FEATURE_ENTRY(201707L, __cpp_lib_shared_ptr_arrays)
    COMPILER_FEATURE_ENTRY(201806L, __cpp_lib_shift)
    COMPILER_FEATURE_ENTRY(202002L, __cpp_lib_smart_ptr_for_overwrite)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_source_location)
    COMPILER_FEATURE_ENTRY(202002L, __cpp_lib_span)
    COMPILER_FEATURE_ENTRY(201902L, __cpp_lib_ssize)
    COMPILER_FEATURE_ENTRY(201711L, __cpp_lib_starts_ends_with)
    COMPILER_FEATURE_ENTRY(201803L, __cpp_lib_string_view)
    COMPILER_FEATURE_ENTRY(201803L, __cpp_lib_syncbuf)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_three_way_comparison)
    COMPILER_FEATURE_ENTRY(201711L, __cpp_lib_to_address)
    COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_to_array)
    COMPILER_FEATURE_ENTRY(201806L, __cpp_lib_type_identity)
    COMPILER_FEATURE_ENTRY(201811L, __cpp_lib_unwrap_ref)
    COMPILER_FEATURE_ENTRY(202106L, __cpp_lib_variant)
};
 
static constexpr CompilerFeature cxx23_core[] = {
    COMPILER_FEATURE_ENTRY(202110L, __cpp_auto_cast)
    COMPILER_FEATURE_ENTRY(202211L, __cpp_constexpr)
    COMPILER_FEATURE_ENTRY(202110L, __cpp_explicit_this_parameter)
    COMPILER_FEATURE_ENTRY(202106L, __cpp_if_consteval)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_implicit_move)
    COMPILER_FEATURE_ENTRY(202211L, __cpp_multidimensional_subscript)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_named_character_escapes)
    COMPILER_FEATURE_ENTRY(202211L, __cpp_range_based_for)
    COMPILER_FEATURE_ENTRY(202011L, __cpp_size_t_suffix)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_static_call_operator)
};
static constexpr CompilerFeature cxx23_lib[] = {
    COMPILER_FEATURE_ENTRY(202106L, __cpp_lib_adaptor_iterator_pair_constructor)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_algorithm_iterator_requirements)
    COMPILER_FEATURE_ENTRY(202302L, __cpp_lib_allocate_at_least)
    COMPILER_FEATURE_ENTRY(202110L, __cpp_lib_associative_heterogeneous_erasure)
    COMPILER_FEATURE_ENTRY(202302L, __cpp_lib_barrier)
    COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_bind_back)
    COMPILER_FEATURE_ENTRY(202110L, __cpp_lib_byteswap)
    COMPILER_FEATURE_ENTRY(202302L, __cpp_lib_common_reference)
    COMPILER_FEATURE_ENTRY(202302L, __cpp_lib_common_reference_wrapper)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_concepts)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_constexpr_bitset)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_constexpr_charconv)
    COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_constexpr_cmath)
    COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_constexpr_memory)
    COMPILER_FEATURE_ENTRY(202106L, __cpp_lib_constexpr_typeinfo)
    COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_containers_ranges)
    COMPILER_FEATURE_ENTRY(202211L, __cpp_lib_expected)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_flat_map)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_flat_set)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_format)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_format_ranges)
    COMPILER_FEATURE_ENTRY(202302L, __cpp_lib_formatters)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_forward_like)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_generator)
    COMPILER_FEATURE_ENTRY(202106L, __cpp_lib_invoke_r)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_ios_noreplace)
    COMPILER_FEATURE_ENTRY(202302L, __cpp_lib_is_implicit_lifetime)
    COMPILER_FEATURE_ENTRY(202011L, __cpp_lib_is_scoped_enum)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_mdspan)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_modules)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_move_iterator_concept)
    COMPILER_FEATURE_ENTRY(202110L, __cpp_lib_move_only_function)
    COMPILER_FEATURE_ENTRY(202110L, __cpp_lib_optional)
    COMPILER_FEATURE_ENTRY(202106L, __cpp_lib_out_ptr)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_print)
    COMPILER_FEATURE_ENTRY(202302L, __cpp_lib_ranges)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_ranges_as_const)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_ranges_as_rvalue)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_ranges_cartesian_product)
    COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_ranges_chunk)
    COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_ranges_chunk_by)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_ranges_contains)
    COMPILER_FEATURE_ENTRY(202302L, __cpp_lib_ranges_enumerate)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_ranges_find_last)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_ranges_fold)
    COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_ranges_iota)
    COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_ranges_join_with)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_ranges_repeat)
    COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_ranges_slide)
    COMPILER_FEATURE_ENTRY(202106L, __cpp_lib_ranges_starts_ends_with)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_ranges_stride)
    COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_ranges_to_container)
    COMPILER_FEATURE_ENTRY(202110L, __cpp_lib_ranges_zip)
    COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_reference_from_temporary)
    COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_shift)
    COMPILER_FEATURE_ENTRY(202106L, __cpp_lib_spanstream)
    COMPILER_FEATURE_ENTRY(202011L, __cpp_lib_stacktrace)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_start_lifetime_as)
    COMPILER_FEATURE_ENTRY(202011L, __cpp_lib_stdatomic_h)
    COMPILER_FEATURE_ENTRY(202011L, __cpp_lib_string_contains)
    COMPILER_FEATURE_ENTRY(202110L, __cpp_lib_string_resize_and_overwrite)
    COMPILER_FEATURE_ENTRY(202102L, __cpp_lib_to_underlying)
    COMPILER_FEATURE_ENTRY(202207L, __cpp_lib_tuple_like)
    COMPILER_FEATURE_ENTRY(202202L, __cpp_lib_unreachable)
};
 
static constexpr CompilerFeature cxx26_core[] = {
    //< Continue to Populate
    COMPILER_FEATURE_ENTRY(202304L, __cpp_core_TODO)
};
static constexpr CompilerFeature cxx26_lib[] = {
    //< Continue to Populate
    COMPILER_FEATURE_ENTRY(202304L, __cpp_lib_TODO)
    COMPILER_FEATURE_ENTRY(202306L, __cpp_lib_constexpr_algorithms)
};
 
static constexpr CompilerFeature cxx29_core[] = {
    //< Continue to Populate
    COMPILER_FEATURE_ENTRY(202604L, __cpp_core_TODO)
};
static constexpr CompilerFeature cxx29_lib[] = {
    //< Continue to Populate
    COMPILER_FEATURE_ENTRY(202604L, __cpp_lib_TODO)
};
 
static constexpr CompilerFeature attributes[] = {
    COMPILER_ATTRIBUTE(202207L, assume)
    COMPILER_ATTRIBUTE(200809L, carries_dependency)
    COMPILER_ATTRIBUTE(201309L, deprecated)
    COMPILER_ATTRIBUTE(201603L, fallthrough)
    COMPILER_ATTRIBUTE(201803L, likely)
    COMPILER_ATTRIBUTE(201603L, maybe_unused)
    COMPILER_ATTRIBUTE(201803L, no_unique_address)
    COMPILER_ATTRIBUTE(201907L, nodiscard)
    COMPILER_ATTRIBUTE(200809L, noreturn)
    COMPILER_ATTRIBUTE(201803L, unlikely)
};
 
inline void show_compiler_specific_info()
{
    std::printf("Compiler specific macros:\n");
    for (auto co : compiler)
        if (std::strcmp(co.first, co.second))
            std::printf("%*s %s\n", -print.longest_macro_name, co.first, co.second);
}
 
inline void print_compiler_feature(const CompilerFeature& x)
{
    if (not ((print.supported_features and x.maybe()) or
            (print.unsupported_features and not x.maybe())))
        return;
    auto print_year_month = [](long n)
    {
        return std::printf("%ld%s%02ld",
            n / 100, print.separate_year_month ? "-" : "", n % 100);
    };
    std::printf("%*s ", -print.longest_macro_name, x.name());
    x.maybe() ? print_year_month(x.data()) :
                    std::printf("------%s", print.separate_year_month ? "-" : "");
    if (print.standard_values)
        std::printf("  %c  ", (x.supported() ? (x.data() > x.std() ? '>' : '=') : '<')),
            print_year_month(x.std());
    std::puts("");
}
 
template<class Container>
inline void show(char const* const title, Container const& co)
{
    if (print.titles)
    {
        std::printf("%-s (", title);
        if (print.counters)
        {
            std::printf("%ld/", std::count_if(std::begin(co), std::end(co),
                [](CompilerFeature x)
                {
                    return x.supported();
                }));
        }
        std::printf("%td)\n", std::distance(std::begin(co), std::end(co)));
    }
    if (print.sort_by_date)
    {
        std::vector<CompilerFeature> v(std::begin(co), std::end(co));
        std::stable_sort(v.begin(), v.end(),
            [](CompilerFeature const& lhs, CompilerFeature const& rhs)
            {
                return lhs.data() < rhs.data();
            });
        std::for_each(v.cbegin(), v.cend(), print_compiler_feature);
    }
    else
        std::for_each(std::begin(co), std::end(co), print_compiler_feature);
    std::puts("");
}
 
inline void show_latest()
{
    auto latest_rev = []() -> int
    {
        return print.cxx29 ? 29 : print.cxx26 ? 26 : print.cxx23 ? 23 : print.cxx20 ? 20 :
               print.cxx17 ? 17 : print.cxx14 ? 14 : print.cxx11 ? 11 : 98;
    };
    std::vector<CompilerFeature> latest;
    auto add = [&latest](CompilerFeature x)
    {
        auto i = std::lower_bound(latest.begin(), latest.end(), x);
        if (i == latest.end() or not (*i == x))
            latest.insert(i, x);
        else if (i->data() < x.data())
            i->data(x.data());
    };
    char text[64];
    latest.reserve(512); // max macros
    if (print.core_features)
    {   // preserve reverse revision insertion order!
        if (print.cxx29) std::for_each(std::begin(cxx29_core), std::end(cxx29_core), add);
        if (print.cxx26) std::for_each(std::begin(cxx26_core), std::end(cxx26_core), add);
        if (print.cxx23) std::for_each(std::begin(cxx23_core), std::end(cxx23_core), add);
        if (print.cxx20) std::for_each(std::begin(cxx20_core), std::end(cxx20_core), add);
        if (print.cxx17) std::for_each(std::begin(cxx17_core), std::end(cxx17_core), add);
        if (print.cxx14) std::for_each(std::begin(cxx14_core), std::end(cxx14_core), add);
        if (print.cxx11) std::for_each(std::begin(cxx11_core), std::end(cxx11_core), add);
        if (print.cxx98) std::for_each(std::begin(cxx98_core), std::end(cxx98_core), add);
        std::snprintf(text, sizeof text, "ALL CORE MACROS UP TO C++%02i", latest_rev());
        show(text, latest);
    }
    latest.clear();
    if (print.lib_features)
    {   // preserve reverse revision insertion order!
        if (print.cxx29) std::for_each(std::begin(cxx29_lib), std::end(cxx29_lib), add);
        if (print.cxx26) std::for_each(std::begin(cxx26_lib), std::end(cxx26_lib), add);
        if (print.cxx23) std::for_each(std::begin(cxx23_lib), std::end(cxx23_lib), add);
        if (print.cxx20) std::for_each(std::begin(cxx20_lib), std::end(cxx20_lib), add);
        if (print.cxx17) std::for_each(std::begin(cxx17_lib), std::end(cxx17_lib), add);
        if (print.cxx14) std::for_each(std::begin(cxx14_lib), std::end(cxx14_lib), add);
        std::snprintf(text, sizeof text, "ALL LIB MACROS UP TO C++%02i", latest_rev());
        show(text, latest);
    }
}
 
int main()
{
    if (print.separated_revisions)
    {
        if (print.cxx98 and print.core_features) show("C++98 CORE", cxx98_core);
        if (print.cxx11 and print.core_features) show("C++11 CORE", cxx11_core);
        if (print.cxx14 and print.core_features) show("C++14 CORE", cxx14_core);
        if (print.cxx14 and print.lib_features ) show("C++14 LIB" , cxx14_lib);
        if (print.cxx17 and print.core_features) show("C++17 CORE", cxx17_core);
        if (print.cxx17 and print.lib_features ) show("C++17 LIB" , cxx17_lib);
        if (print.cxx20 and print.core_features) show("C++20 CORE", cxx20_core);
        if (print.cxx20 and print.lib_features ) show("C++20 LIB" , cxx20_lib);
        if (print.cxx23 and print.core_features) show("C++23 CORE", cxx23_core);
        if (print.cxx23 and print.lib_features ) show("C++23 LIB" , cxx23_lib);
        if (print.cxx26 and print.core_features) show("C++26 CORE", cxx26_core);
        if (print.cxx26 and print.lib_features ) show("C++26 LIB" , cxx26_lib);
        if (print.cxx29 and print.core_features) show("C++29 CORE", cxx29_core);
        if (print.cxx29 and print.lib_features ) show("C++29 LIB" , cxx29_lib);
    }
    if (print.latest_revisions) show_latest();
    if (print.attributes) show("ATTRIBUTES", attributes);
    if (print.compiler_specific) show_compiler_specific_info();
}

Possible output:

C++11 CORE (20/20)
__cpp_alias_templates                        2007-04  =  2007-04
__cpp_attributes                             2008-09  =  2008-09
__cpp_constexpr                              2021-10  >  2007-04
__cpp_constexpr_in_decltype                  2017-11  =  2017-11
... truncated ...
 
C++14 CORE (9/9)
__cpp_aggregate_nsdmi                        2013-04  =  2013-04
__cpp_binary_literals                        2013-04  =  2013-04
__cpp_constexpr                              2021-10  >  2013-04
... truncated ...
 
C++14 LIB (20/20)
__cpp_lib_chrono_udls                        2013-04  =  2013-04
__cpp_lib_complex_udls                       2013-09  =  2013-09
__cpp_lib_exchange_function                  2013-04  =  2013-04
... truncated ...
 
C++17 CORE (20/20)
__cpp_aggregate_bases                        2016-03  =  2016-03
__cpp_aligned_new                            2016-06  =  2016-06
__cpp_capture_star_this                      2016-03  =  2016-03
__cpp_constexpr                              2021-10  >  2016-03
... truncated ...
 
C++17 LIB (49/49)
__cpp_lib_addressof_constexpr                2016-03  =  2016-03
__cpp_lib_allocator_traits_is_always_equal   2014-11  =  2014-11
... truncated ...
 
C++20 CORE (17/18)
__cpp_aggregate_paren_init                   2019-02  =  2019-02
__cpp_char8_t                                2018-11  =  2018-11
__cpp_concepts                               2020-02  =  2020-02
... truncated ...
 
C++20 LIB (64/67)
__cpp_lib_array_constexpr                    2018-11  =  2018-11
__cpp_lib_assume_aligned                     2018-11  =  2018-11
__cpp_lib_atomic_flag_test                   2019-07  =  2019-07
... truncated ...
 
C++23 CORE (2/11)
__cpp_char8_t                                2018-11  <  2022-07
__cpp_consteval                              2018-11  <  2022-11
... truncated ...
 
C++23 LIB (16/64)
__cpp_lib_adaptor_iterator_pair_constructor  2021-06  =  2021-06
__cpp_lib_algorithm_iterator_requirements    -------  <  2022-07
__cpp_lib_allocate_at_least                  -------  <  2023-02
__cpp_lib_associative_heterogeneous_erasure  -------  <  2021-10
__cpp_lib_barrier                            2019-07  <  2023-02
... truncated ...
 
ALL CORE MACROS UP TO C++23 (55/65)
__cpp_aggregate_bases                        2016-03  =  2016-03
__cpp_aggregate_nsdmi                        2013-04  =  2013-04
__cpp_aggregate_paren_init                   2019-02  =  2019-02
__cpp_alias_templates                        2007-04  =  2007-04
... truncated ...
 
ALL LIB MACROS UP TO C++23 (135/185)
__cpp_lib_adaptor_iterator_pair_constructor  2021-06  =  2021-06
__cpp_lib_addressof_constexpr                2016-03  =  2016-03
__cpp_lib_algorithm_iterator_requirements    -------  <  2022-07
__cpp_lib_allocate_at_least                  -------  <  2023-02
__cpp_lib_allocator_traits_is_always_equal   2014-11  =  2014-11
... truncated ...
 
ATTRIBUTES (8/10)
assume                                       -------  <  2022-07
carries_dependency                           -------  <  2008-09
deprecated                                   2013-09  =  2013-09
fallthrough                                  2016-03  =  2016-03
... truncated ...
 
Compiler specific macros:
__cplusplus                                  202100L
__GNUG__                                     12
__GNUC_MINOR__                               2
__GNUC_PATCHLEVEL__                          1

See also

Library feature-test macros (C++20) defined in the header <version>
C++ documentation for Macro Symbol Index
1. The official document on Feature-Test Recommendations
2. Source code to dump compiler features

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/feature_test