Przejdź do głównej zawartości

Feature testing (od C++20)

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

Attributes

pub__has_cpp_attribute( attribute-token )

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

For standard attributes, it will expand to the year and monthin which the attribute was added to the working draft (see table below), 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 (od C++23) and defined but cannot be used anywhere else.

attribute-tokenAttributeValueStandardPaper(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
201907L
(C++17)
(C++20)
P0189R1
P1301R4
noreturn[[noreturn]]200809L(C++11)N2761
unlikely[[unlikely]]201803L(C++20)P0479R5

Language features

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

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

Macro nameFeatureValueStdPaper(s)
__cpp_aggregate_basesAggregate classes withbase classes201603L(C++17)P0017R1
__cpp_aggregate_nsdmiAggregate classes withdefault miber initializers201304L(C++14)N3653
__cpp_aggregate_paren_initAggregate initialization in the form of direct initialization201902L(C++20)P0960R3
__cpp_alias_tiplatesAlias tiplates200704L(C++11)N2258
__cpp_aligned_newDynamic miory allocation for over-aligned data201606L(C++17)P0035R4
__cpp_attributesAttributes200809L(C++11)N2761
__cpp_auto_castauto(x) and auto{x}202110L(C++23)P0849R8
__cpp_binary_literalsBinary literals201304L(C++14)N3472
__cpp_capture_star_thisLambda capture of *this by value as [=,*this]201603L(C++17)P0018R3
__cpp_char8_tchar8_t201811L(C++20)P0482R6
__cpp_char8_tchar8_t compatibility and portability fix (allow initialization of (unsigned) char arrays from UTF-8 string literals)202207L(C++20)(DR)P2513R4
__cpp_conceptsConcepts201907L(C++20)P0734R0
P1084R2
P1452R2
__cpp_conceptsConditional trivial special miber functions202002L(C++20)P0848R3
P2493R0
__cpp_conditional_explicitexplicit(bool)201806L(C++20)P0892R2
__cpp_constevalImmediate functions201811L(C++20)P1073R3
__cpp_constevalMaking consteval propagate up202211L(C++20)(DR)P2564R3
__cpp_constexprconstexpr200704L(C++11)N2235
__cpp_constexprRelaxed constexpr, non-const constexpr methods201304L(C++14)N3652
__cpp_constexprConstexpr lambda201603L(C++17)P0170R1
__cpp_constexprVirtual function calls in constant expressions201806L(C++20)P1064R0
__cpp_constexprtry-catch blocks in consexpr functions, dynamic_cast and polymorphic typeid in constant expressions201811L(C++20)P1002R1
P1327R1
__cpp_constexprTrivial default initialization and asm-declaration in constexpr functions201907L(C++20)P1331R2
P1668R1
__cpp_constexprChanging the active miber of a union in constant evaluation202002L(C++20)P1330R0
__cpp_constexprNon-literal variables, labels, and goto statients in constexpr functions202110L(C++23)P2242R3
__cpp_constexprRelaxing some restrictions on constexpr functions and function tiplates202207L(C++23)P2448R2
__cpp_constexprPermitting static constexpr variables in constexpr functions202211L(C++23)P2647R1
__cpp_constexpr_dynamic_allocOperations for dynamic storage duration in constexpr functions201907L(C++20)P0784R7
__cpp_constexpr_in_decltypeGeneration of function and variable definitions when needed for constant evaluation201711L(C++11)(DR)P0859R0
__cpp_constinitconstinit201907L(C++20)P1143R2
__cpp_decltypedecltype200707L(C++11)N2343
__cpp_decltype_autoReturn type deduction for normal functions201304L(C++14)N3638
__cpp_deduction_guidesTiplate argument deduction for class tiplates201703L(C++17)P0091R3
P0512R0
P0620R0
__cpp_deduction_guidesCTAD for aggregates and aliases201907L(C++20)P1814R0
P1816R0
__cpp_delegating_constructorsDelegating constructors200604L(C++11)N1986
__cpp_designated_initializersDesignated initializer201707L(C++20)P0329R4
__cpp_enumerator_attributesAttributes for enumerators201411L(C++17)N4266
__cpp_explicit_this_parameterExplicit object parameter202110L(C++23)P0847R7
__cpp_fold_expressionsFold expressions201603L(C++17)N4295
P0036R0
__cpp_generic_lambdasGeneric lambda expressions201304L(C++14)N3649
__cpp_generic_lambdasExplicit tiplate parameter list for generic lambdas201707L(C++20)P0428R2
__cpp_guaranteed_copy_elisionGuaranteed copy elision through simplified value categories201606L(C++17)P0135R1
__cpp_hex_floatHexadecimal floating literals201603L(C++17)P0245R1
__cpp_if_constevalconsteval if202106L(C++23)P1938R3
__cpp_if_constexprconstexpr if201606L(C++17)P0292R2
__cpp_impl_coroutineCoroutines (compiler support)201902L(C++20)P0912R5
LWG3393
__cpp_impl_destroying_deleteDestroying operator delete (compiler support)201806L(C++20)P0722R3
__cpp_impl_three_way_comparisonThree-way comparison (compiler support)201907L(C++20)P0515R3
P0768R1
P1185R2
P1630R1
__cpp_implicit_moveSimpler implicit move202207L(C++23)P2266R3
__cpp_inheriting_constructorsInheriting constructors200802L(C++11)N2540
__cpp_inheriting_constructorsRewording inheriting constructors201511L(C++11)(DR)P0136R1
__cpp_init_capturesLambda init-capture201304L(C++14)N3648
__cpp_init_capturesAllow pack expansion in lambda init-capture201803L(C++20)P0780R2
__cpp_initializer_listsList-initialization and std::initializer_list200806L(C++11)N2672
__cpp_inline_variablesInline variables201606L(C++17)P0386R2
__cpp_lambdasLambda expressions200907L(C++11)N2927
__cpp_modulesModules201907L(C++20)P1103R3
P1811R0
__cpp_multidimensional_subscriptMultidimensional subscript operator202110L(C++23)P2128R6
__cpp_multidimensional_subscriptstatic operator[]202211L(C++23)P2589R1
__cpp_named_character_escapesNamed universal character escapes202207L(C++23)P2071R2
__cpp_namespace_attributesAttributes for namespaces201411L(C++17)N4266
__cpp_noexcept_function_typeMake exception specifications be part of the type systi201510L(C++17)P0012R1
__cpp_nontype_tiplate_argsAllow constant evaluation for all non-type tiplate arguments201411L(C++17)N4268
__cpp_nontype_tiplate_argsClass types and floating-point types in non-type tiplate parameters201911L(C++20)P1907R1
__cpp_nontype_tiplate_parameter_autoDeclaring non-type tiplate parameters withauto201606L(C++17)P0127R2
__cpp_nsdmiNon-static data miber initializers200809L(C++11)N2756
__cpp_range_based_forRange-based for loop200907L(C++11)N2930
__cpp_range_based_forRange-based for loop withdifferent begin/end types201603L(C++17)P0184R0
__cpp_range_based_forLifetime extension in range-based for202211L(C++23)P2718R0
__cpp_raw_stringsRaw string literals200710L(C++11)N2442
__cpp_ref_qualifiersref-qualifiers200710L(C++11)N2439
__cpp_return_type_deductionReturn type deduction for normal functions201304L(C++14)N3638
__cpp_rvalue_referencesRvalue reference200610L(C++11)N2118
__cpp_size_t_suffixLiteral suffixes for size_t and its signed version202011L(C++23)P0330R8
__cpp_sized_deallocationSized deallocation201309L(C++14)N3778
__cpp_static_assertstatic_assert200410L(C++11)N1720
__cpp_static_assertSingle-argument static_assert201411L(C++17)N3928
__cpp_static_call_operatorstatic operator()202207L(C++23)P1169R4
__cpp_structured_bindingsStructured bindings201606L(C++17)P0217R3
__cpp_tiplate_tiplate_argsMatching of tiplate tiplate-arguments201611L(C++17)P0522R0
__cpp_threadsafe_static_initDynamic initialization and destruction withconcurrency200806L(C++11)N2660
__cpp_unicode_charactersNew character types (char16_t and char32_t)200704L(C++11)N2249
__cpp_unicode_literalsUnicode string literals200710L(C++11)N2442
__cpp_user_defined_literalsUser-defined literals200809L(C++11)N2765
__cpp_using_enumusing enum201907L(C++20)P1099R5
__cpp_variable_tiplatesVariable tiplates201304L(C++14)N3651
__cpp_variadic_tiplatesVariadic tiplates200704L(C++11)N2242
__cpp_variadic_usingPack expansions in using-declarations201611L(C++17)P0195R2

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 monthwhen the corresponding feature has been included in the working draft.

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

Macro nameFeatureValueHeaderStdPaper(s)
__cpp_lib_adaptor_iterator_pair_constructorIterator pair constructors for std::stack and std::queue202106L<queue> <stack>(C++23)P1425R4
__cpp_lib_addressof_constexprConstexpr std::addressof201603L<miory>(C++17)LWG2296
__cpp_lib_algorithm_iterator_requirientsRanges iterators as inputs to non-Ranges algorithms202207L<algorithm> <miory> <numeric>(C++23)P2408R5
__cpp_lib_allocate_at_leastSize-feedback in the Allocator interface, e.g.: std::allocator::allocate_at_least, std::allocator_traits::allocate_at_least202302L<miory>(C++23)P0401R6 P2652R2
__cpp_lib_allocator_traits_is_always_equalstd::allocator_traits::is_always_equal201411L<miory> <scoped_allocator> <string> <deque> <forward_list> <list> <vector> <map> <set> <unordered_map> <unordered_set>(C++17)N4258
__cpp_lib_anystd::any201606L<any>(C++17)P0220R1 P0032R3
__cpp_lib_applystd::apply201603L<tuple>(C++17)P0220R1
__cpp_lib_array_constexprConstexpr for std::reverse_iterator, std::move_iterator, std::array and range access201603L<iterator> <array>(C++17)P0031R0
__cpp_lib_array_constexprConstexprIterator; 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_conststd::as_const201510L<utility>(C++17)P0007R1
__cpp_lib_associative_heterogeneous_erasureHeterogeneous erasure in associative containers and unordered associative containers202110L<map> <set> <unordered_map> <unordered_set>(C++23)P2077R3
__cpp_lib_assume_alignedstd::assume_aligned201811L<miory>(C++20)P1007R3
__cpp_lib_atomic_flag_teststd::atomic_flag::test201907L<atomic>(C++20)P1135R6
__cpp_lib_atomic_floatFloating-point atomic201711L<atomic>(C++20)P0020R6
__cpp_lib_atomic_is_always_lock_freeconstexpr atomic<T>::is_always_lock_free201603L<atomic>(C++17)P0152R1
__cpp_lib_atomic_lock_free_type_aliasesatomic lockfree integral types (std::atomic_signed_lock_free, std::atomic_unsigned_lock_free)201907L<atomic>(C++20)P1135R6
__cpp_lib_atomic_refstd::atomic_ref201806L<atomic>(C++20)P0019R8
__cpp_lib_atomic_shared_ptrstd::atomic<std::shared_ptr>201711L<miory>(C++20)P0718R2
__cpp_lib_atomic_value_initializationFixing atomic initialization (value-initialize std::atomic by default)201911L<atomic> <miory>(C++20)P0883R2
__cpp_lib_atomic_waitEfficient std::atomic waiting201907L<atomic>(C++20)P1135R6
__cpp_lib_barrierstd::barrier201907L<barrier>(C++20)P1135R6
__cpp_lib_barrierstd::barrier's phase completion guarantees202302L<barrier>(C++23)P2588R3
__cpp_lib_bind_backstd::bind_back202202L<functional>(C++23)P2387R3
__cpp_lib_bind_frontstd::bind_front201907L<functional>(C++20)P0356R5 P1651R0
__cpp_lib_bit_caststd::bit_cast201806L<bit>(C++20)P0476R2
__cpp_lib_bitopsBit operations201907L<bit>(C++20)P0553R4
__cpp_lib_bool_constantstd::bool_constant201505L<type_traits>(C++17)N4389
__cpp_lib_bounded_array_traitsstd::is_bounded_array, std::is_unbounded_array201902L<type_traits>(C++20)P1357R1
__cpp_lib_boyer_moore_searcherSearchers201603L<functional>(C++17)P0220R1
__cpp_lib_bytestd::byte201603L<cstddef>(C++17)P0298R3
__cpp_lib_byteswapstd::byteswap202110L<bit>(C++23)P1272R4
__cpp_lib_char8_tLibrary support for char8_t201907L<atomic> <filesysti> <istream> <limits> <locale> <ostream> <string> <string_view>(C++20)P0482R6 P1423R3
__cpp_lib_chronoRounding functions for std::chrono::duration and std::chrono::time_point201510L<chrono>(C++17)P0092R1
__cpp_lib_chronoConstexpr for all the miber functions of std::chrono::duration and std::chrono::time_point201611L<chrono>(C++17)P0505R0
__cpp_lib_chronoCalendars and Time Zones201907L<chrono>(C++20)P0355R7 P1466R3
__cpp_lib_chrono_udlsUser-defined literals for time types201304L<chrono>(C++14)N3642
__cpp_lib_clampstd::clamp201603L<algorithm>(C++17)P0025R0
__cpp_lib_common_referenceMake std::common_reference_t of std::reference_wrapper a reference type202302L<type_traits>(C++23)P2655R3
__cpp_lib_common_reference_wrapperMake std::common_reference_t of std::reference_wrapper a reference type202302L<functional>(C++23)P2655R3
__cpp_lib_complex_udlsUser-defined Literals for std::complex201309L<complex>(C++14)N3779
__cpp_lib_conceptsStandard library concepts202002L<concepts>(C++20)P0898R3 P1754R1 P1964R2
__cpp_lib_conceptsMove-only types for equality_comparable_with, totally_ordered_with, and three_way_comparable_with202207L<compare> <concepts>(C++23)P2404R3
__cpp_lib_constexpr_algorithmsConstexpr for algorithms201806L<algorithm>(C++20)P0202R3 P0879R0 LWG3256
__cpp_lib_constexpr_bitsetA more constexpr std::bitset202207L<bitset>(C++23)P2417R2
__cpp_lib_constexpr_charconvAdd constexpr modifiers to functions std::to_chars and std::from_chars for integral types202207L<charconv>(C++23)P2291R3
__cpp_lib_constexpr_cmathConstexpr for mathiatical functions in <cmath> and <cstdlib>202202L<cmath> <cstdlib>(C++23)P0533R9
__cpp_lib_constexpr_complexConstexpr for std::complex201711L<complex>(C++20)P0415R1
__cpp_lib_constexpr_dynamic_allocConstexpr for std::allocator and related utilities201907L<miory>(C++20)P0784R7
__cpp_lib_constexpr_functionalMisc constexpr bits (std::default_searcher); constexpr INVOKE201907L<functional>(C++20)P1032R1 P1065R2
__cpp_lib_constexpr_iteratorMisc constexpr bits (std::insert_iterator et al.)201811L<iterator>(C++20)P1032R1
__cpp_lib_constexpr_mioryConstexpr in std::pointer_traits201811L<miory>(C++20)P1006R1
__cpp_lib_constexpr_mioryConstexpr std::unique_ptr202202L<miory>(C++23)P2273R3
__cpp_lib_constexpr_numericConstexpr for algorithms in <numeric>201911L<numeric>(C++20)P1645R1
__cpp_lib_constexpr_stringConstexpr for std::string201907L<string>(C++20)P0426R1 P1032R1 P0980R1
__cpp_lib_constexpr_string_viewMisc constexpr bits (std::string_view::copy)201811L<string_view>(C++20)P0426R1 P1032R1
__cpp_lib_constexpr_tupleMisc constexpr bits (std::tuple::operator= et al.)201811L<tuple>(C++20)P1032R1
__cpp_lib_constexpr_typeinfoConstexpr for std::type_info::operator==202106L<typeinfo>(C++23)P1328R1
__cpp_lib_constexpr_utilityMisc constexpr bits (std::pair::operator= et al.)201811L<utility>(C++20)P1032R1
__cpp_lib_constexpr_vectorConstexpr for std::vector201907L<vector>(C++20)P1004R2
__cpp_lib_containers_rangesRanges-aware construction and insertion for containers and strings202202L<vector> <list> <forward_list > <map> <set> <unordered_map> <unordered_set> <deque> <queue> <stack> <string>(C++23)P1206R7
__cpp_lib_coroutineCoroutines (library support)201902L<coroutine>(C++20)P0912R5 LWG3393
__cpp_lib_destroying_deleteDestroying operator delete (library support)201806L<new>(C++20)P0722R3
__cpp_lib_enable_shared_from_thisstd::enable_shared_from_this::weak_from_this201603L<miory>(C++17)P0033R1
__cpp_lib_endianstd::endian201907L<bit>(C++20)P0463R1 P1612R1
__cpp_lib_erase_ifUniform container erasure202002L<string> <deque> <forward_list > <list> <vector> <map> <set> <unordered_map> <unordered_set>(C++20)P1209R0 P1115R3
__cpp_lib_exchange_functionstd::exchange201304L<utility>(C++14)N3668
__cpp_lib_executionExecution policies201603L<execution>(C++17)P0024R2
__cpp_lib_executionstd::execution::unsequenced_policy201902L<execution>(C++20)P1001R2
__cpp_lib_expectedclass tiplate std::expected202202L<expected>(C++23)P0323R12
__cpp_lib_expectedMonadic functions for std::expected202211L<expected>(C++23)P2505R5
__cpp_lib_filesystiFilesysti library201703L<filesysti>(C++17)P0218R1 P0219R1 P0392R0 P0317R1
__cpp_lib_flat_mapstd::flat_map and std::flat_multimap202207L<flat_map>(C++23)P0429R9
__cpp_lib_flat_setstd::flat_set and std::flat_multiset202207L<flat_set>(C++23)P1222R4 LWG3751
__cpp_lib_formatText formatting201907L<format>(C++20)P0645R10 P1361R2 P1652R1
__cpp_lib_formatCompile-time format string checks; Reducing parameterization of std::vformat_to202106L<format>(C++20) (DR)P2216R3
__cpp_lib_formatFixing locale handling in chrono formatters; Supporting non-const-formattable types202110L<format>(C++20) (DR)P2372R3 P2418R2
__cpp_lib_formatExposing std::basic_format_string; clarify handling of encodings in localized formatting of chrono types202207L<format>(C++23)P2419R2 P2508R1
__cpp_lib_format_rangesFormatting ranges202207L<format>(C++23)P2286R8 P2585R1 LWG3750
__cpp_lib_formattersFormatting std:🧵:id and std::stacktrace202302L<stacktrace> <thread>(C++23)P2693R1
__cpp_lib_forward_likestd::forward_like202207L<utility>(C++23)P2445R1
__cpp_lib_gcd_lcmstd::gcd, std::lcm201606L<numeric>(C++17)P0295R0
__cpp_lib_generatorstd::generator: synchronous coroutine generator for ranges202207L<generator>(C++23)P2502R2
__cpp_lib_generic_associative_lookupHeterogeneous comparison lookup in associative containers201304L<map> <set>(C++14)N3657
__cpp_lib_generic_unordered_lookupHeterogeneous comparison lookup in unordered associative containers201811L<unordered_map> <unordered_set>(C++20)P0919R3
__cpp_lib_hardware_interference_sizeconstexpr std::hardware_{constructive, destructive}_interference_size201703L<new>(C++17)P0154R1
__cpp_lib_has_unique_object_representationsstd::has_unique_object_representations201606L<type_traits>(C++17)P0258R2
__cpp_lib_hypot3-argument overload of std::hypot201603L<cmath>(C++17)P0030R1
__cpp_lib_incomplete_container_elientsMinimal incomplete type support for std::forward_list, std::list, and std::vector201505L<forward_list > <list> <vector>(C++17)N4510
__cpp_lib_int_pow2Integral 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_functionsInteger comparison functions202002L<utility>(C++20)P0586R2
__cpp_lib_integer_sequenceCompile-time integer sequences201304L<utility>(C++14)N3658
__cpp_lib_integral_constant_callablestd::integral_constant::operator()201304L<type_traits>(C++14)N3545
__cpp_lib_interpolatestd::lerp, std::midpoint201902L<cmath> <numeric>(C++20)P0811R3
__cpp_lib_invokestd::invoke201411L<functional>(C++17)N4169
__cpp_lib_invoke_rstd::invoke_r202106L<functional>(C++23)P2136R3
__cpp_lib_ios_noreplaceSupport exclusive mode for fstreams202207L<ios>(C++23)P2467R1
__cpp_lib_is_aggregatestd::is_aggregate201703L<type_traits>(C++17)LWG2911
__cpp_lib_is_constant_evaluatedstd::is_constant_evaluated201811L<type_traits>(C++20)P0595R2
__cpp_lib_is_finalstd::is_final201402L<type_traits>(C++14)LWG2112
__cpp_lib_is_implicit_lifetimestd::is_implicit_lifetime202302L<type_traits>(C++23)P2674R1
__cpp_lib_is_invocablestd::is_invocable, std::invoke_result201703L<type_traits>(C++17)P0604R0
__cpp_lib_is_layout_compatiblestd::is_layout_compatible201907L<type_traits>(C++20)P0466R5
__cpp_lib_is_nothrow_convertiblestd::is_nothrow_convertible201806L<type_traits>(C++20)P0758R1 LWG3356
__cpp_lib_is_null_pointerstd::is_null_pointer201309L<type_traits>(C++14)LWG2247
__cpp_lib_is_pointer_interconvertiblePointer-interconvertibility traits: std::is_pointer_interconvertible_with_class, std::is_pointer_interconvertible_base_of201907L<type_traits>(C++20)P0466R5
__cpp_lib_is_scoped_enumstd::is_scoped_enum202011L<type_traits>(C++23)P1048R1
__cpp_lib_is_swappablenothrow-swappable traits201603L<type_traits>(C++17)P0185R1
__cpp_lib_jthreadStop token and joining thread201911L<stop_token> <thread>(C++20)P0660R10 P1869R1
__cpp_lib_latchstd::latch201907L<latch>(C++20)P1135R6
__cpp_lib_launderCore Issue 1776: Replacient of class objects containing reference mibers (std::launder)201606L<new>(C++17)P0137R1
__cpp_lib_list_riove_return_typeChange the return type of the riove(), riove_if() and unique() mibers of std::forward_list and std::list201806L<forward_list > <list>(C++20)P0646R1
__cpp_lib_logical_traitsLogical operations on type traits201510L<type_traits>(C++17)P0013R1
__cpp_lib_make_from_tuplestd::make_from_tuple()201606L<tuple>(C++17)P0209R2
__cpp_lib_make_reverse_iteratorstd::make_reverse_iterator201402L<iterator>(C++14)LWG2285
__cpp_lib_make_uniquestd::make_unique201304L<miory>(C++14)N3656
__cpp_lib_map_try_iplacestd::map::try_iplace, std::map::insert_or_assign201411L<map>(C++17)N4279
__cpp_lib_math_constantsMathiatical constants201907L<numbers>(C++20)P0631R8
__cpp_lib_math_special_functionsMathiatical special functions for C++17201603L<cmath>(C++17)P0226R1
__cpp_lib_mdspanstd::mdspan202207L<mdspan>(C++23)P0009R18 P2599R2 P2604R0 P2613R1
__cpp_lib_miory_resourcestd::pmr::miory_resource201603L<miory_resource>(C++17)P0220R1
__cpp_lib_modulesStandard library modules stdand std.compat202207L(C++23)P2465R3
__cpp_lib_move_iterator_conceptMake std::move_iterator<T*> a random access iterator202207L<iterator>(C++23)P2520R0
__cpp_lib_move_only_functionstd::move_only_function202110L<functional>(C++23)P0288R9
__cpp_lib_node_extractSplicing 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_nonmiber_container_accessstd::size(), std::data() and std::ipty()201411L<iterator> <array> <deque> <forward_list > <list> <map> <regex> <set> <string> <unordered_map> <unordered_set> <vector>(C++17)N4280
__cpp_lib_not_fnstd::not_fn()201603L<functional>(C++17)P0005R4
__cpp_lib_null_iteratorsNull LegacyForwardIterators201304L<iterator>(C++14)N3644
__cpp_lib_optionalstd::optional201606L<optional>(C++17)P0220R1 P0032R3 P0307R2
__cpp_lib_optionalFully constexpr std::optional202106L<optional>(C++20) (DR)P2231R1
__cpp_lib_optionalMonadic operations in std::optional202110L<optional>(C++23)P0798R8 LWG3621
__cpp_lib_out_ptrstd::out_ptr, std::inout_ptr202106L<miory>(C++23)P1132R7
__cpp_lib_parallel_algorithmParallel algorithms201603L<algorithm> <numeric>(C++17)P0024R2
__cpp_lib_polymorphic_allocatorstd::pmr::polymorphic_allocator<> as a vocabulary type201902L<miory_resource>(C++20)P0339R6 LWG3437
__cpp_lib_printFormatted output202207L<ostream> <print>(C++23)P2093R14
__cpp_lib_quoted_string_iostd::quoted201304L<iomanip>(C++14)N3654
__cpp_lib_rangesRanges library and constrained algorithms201911L<algorithm> <functional> <iterator> <miory> <ranges>(C++20)P0896R4 P1035R7 P1716R3
__cpp_lib_rangesNon-default-initializable views202106L(C++20) (DR)P2325R3
__cpp_lib_rangesViews withownership202110L(C++20) (DR)P2415R2
__cpp_lib_rangesstd::ranges::range_adaptor_closure202202L(C++23)P2387R3
__cpp_lib_rangesRelaxing range adaptors to allow for move-only types202207L(C++23)P2494R2
__cpp_lib_rangesRioving 'poison pill' overloads in ranges::begin, ranges::end, ranges::rbegin, ranges::rend, and ranges::size202211L(C++23)P2602R2
__cpp_lib_rangesRelaxing ranges to allow certain projections202302L(C++23)P2609R3
__cpp_lib_ranges_as_conststd::const_iterator, std::ranges::as_const_view202207L<ranges>(C++23)P2278R4
__cpp_lib_ranges_as_rvaluestd::ranges::as_rvalue_view202207L<ranges>(C++23)P2446R2
__cpp_lib_ranges_cartesian_productstd::ranges::cartesian_product_view202207L<ranges>(C++23)P2374R4 P2540R1
__cpp_lib_ranges_chunkstd::ranges::chunk_view202202L<ranges>(C++23)P2442R1
__cpp_lib_ranges_chunk_bystd::ranges::chunk_by_view202202L<ranges>(C++23)P2443R1
__cpp_lib_ranges_containsstd::ranges::contains202207L<algorithm>(C++23)P2302R4
__cpp_lib_ranges_enumeratestd::ranges::enumerate_view202302L<ranges>(C++23)P2164R9
__cpp_lib_ranges_find_laststd::find_last()202207L<algorithm>(C++23)P1223R5
__cpp_lib_ranges_foldstd::ranges fold algorithms202207L<algorithm>(C++23)P2322R6
__cpp_lib_ranges_iotastd::ranges::iota202202L<numeric>(C++23)P2440R1
__cpp_lib_ranges_join_withstd::ranges::join_with_view202202L<ranges>(C++23)P2441R2
__cpp_lib_ranges_repeatstd::ranges::repeat_view202207L<ranges>(C++23)P2474R2
__cpp_lib_ranges_slidestd::ranges::slide_view202202L<ranges>(C++23)P2442R1
__cpp_lib_ranges_starts_ends_withstd::ranges::starts_with, std::ranges::ends_with202106L<algorithm>(C++23)P1659R3
__cpp_lib_ranges_stridestd::ranges::stride_view202207L<ranges>(C++23)P1899R3
__cpp_lib_ranges_to_containerstd::ranges::to202202L<ranges>(C++23)P1206R7
__cpp_lib_ranges_zipstd::ranges::zip_view, std::ranges::zip_transform_view, std::ranges::adjacent_view, std::ranges::adjacent_transform_view202110L<ranges> <tuple> <utility>(C++23)P2321R2
__cpp_lib_raw_miory_algorithmsExtending miory managient tools201606L<miory>(C++17)P0040R3
__cpp_lib_reference_from_tiporarystd::reference_constructs_from_tiporary and std::reference_converts_from_tiporary202202L<type_traits>(C++23)P2255R2
__cpp_lib_riove_cvrefstd::riove_cvref201711L<type_traits>(C++20)P0550R2
__cpp_lib_result_of_sfinaestd::result_of and SFINAE201210L<type_traits> <functional>(C++14)N3462
__cpp_lib_robust_nonmodifying_seq_opsMaking 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_samplestd::sample201603L<algorithm>(C++17)P0220R1
__cpp_lib_scoped_lockstd::scoped_lock201703L<mutex>(C++17)P0156R2
__cpp_lib_siaphorestd::counting_siaphore, std::binary_siaphore201907L<siaphore>(C++20)P1135R6
__cpp_lib_shared_mutexstd::shared_mutex (untimed)201505L<shared_mutex>(C++17)N4508
__cpp_lib_shared_ptr_arraysstd::shared_ptr<T[]>201611L<miory>(C++17)P0497R0
__cpp_lib_shared_ptr_arraysArray support of std::make_shared201707L<miory>(C++20)P0674R1
__cpp_lib_shared_ptr_weak_typeshared_ptr::weak_type201606L<miory>(C++17)P0163R0
__cpp_lib_shared_timed_mutexstd::shared_timed_mutex201402L<shared_mutex>(C++14)N3891
__cpp_lib_shiftstd::shift_left and std::shift_right201806L<algorithm>(C++20)P0769R2
__cpp_lib_shiftstd::ranges::shift_left and std::ranges::shift_right202202L<algorithm>(C++23)P2440R1
__cpp_lib_smart_ptr_for_overwriteSmart pointer creation withdefault initialization (std::allocate_shared_for_overwrite, std::make_shared_for_overwrite, std::make_unique_for_overwrite)202002L<miory>(C++20)P1020R1 P1973R1
__cpp_lib_source_locationSource-code information capture (std::source_location)201907L<source_location>(C++20)P1208R6
__cpp_lib_spanstd::span202002L<span>(C++20)P0122R7 LWG3274 P1024R3 P1976R2
__cpp_lib_spanstreamstd::spanbuf, std::spanstream202106L<span_stream>(C++23)P0448R4
__cpp_lib_ssizestd::ssize and unsigned std::span::size201902L<iterator>(C++20)P1227R2
__cpp_lib_stacktraceStacktrace library202011L<stacktrace>(C++23)P0881R7
__cpp_lib_start_lifetime_asExplicit lifetime managient (std::start_lifetime_as)202207L<miory>(C++23)P2590R2
__cpp_lib_starts_ends_withString 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_hCompatibility header for C atomic operations202011L<stdatomic.h>(C++23)P0943R6
__cpp_lib_string_containscontains functions of std::basic_string and std::basic_string_view202011L<string> <string_view>(C++23)P1679R3
__cpp_lib_string_resize_and_overwritestd::basic_string::resize_and_overwrite202110L<string>(C++23)P1072R10
__cpp_lib_string_udlsUser-defined literals for string types201304L<string>(C++14)N3642
__cpp_lib_string_viewstd::string_view201606L<string> <string_view>(C++17)P0220R1 P0254R2
__cpp_lib_string_viewConstexprIterator201803L<string> <string_view>(C++20)P0858R0 LWG3257
__cpp_lib_syncbufSynchronized buffered ostream (std::syncbuf, std::osyncstream) and manipulators201803L<syncstream>(C++20)P0053R7 P0753R2
__cpp_lib_three_way_comparisonThree-way comparison (library support); adding three-way comparison to the library201907L<compare>(C++20)P0768R1 P1614R2
__cpp_lib_to_addressUtility to convert a pointer to a raw pointer (std::to_address)201711L<miory>(C++20)P0653R2
__cpp_lib_to_arraystd::to_array201907L<array>(C++20)P0325R4
__cpp_lib_to_charsElientary string conversions (std::to_chars, std::from_chars)201611L<charconv>(C++17)P0067R5 P0682R1 LWG3137
__cpp_lib_to_underlyingstd::to_underlying202102L<utility>(C++23)P1682R2
__cpp_lib_transformation_trait_aliasesAlias tiplates for TransformationTraits201304L<type_traits>(C++14)N3655
__cpp_lib_transparent_operatorsTransparent operator functors (std::less<> et al.)201210L<functional>(C++14)N3421
__cpp_lib_transparent_operatorsTransparent std::owner_less (std::owner_less<void>)201510L<miory> <functional>(C++17)P0074R0
__cpp_lib_tuple_elient_tstd::tuple_elient_t201402L<tuple>(C++14)N3887
__cpp_lib_tuple_likeCompatibility 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_typeAddressing tuples by type201304L<tuple> <utility>(C++14)N3670
__cpp_lib_type_identitystd::type_identity201806L<type_traits>(C++20)P0887R1
__cpp_lib_type_trait_variable_tiplatesType traits variable tiplates (std::is_void_v, etc)201510L<type_traits>(C++17)P0006R0
__cpp_lib_uncaught_exceptionsstd::uncaught_exceptions201411L<exception>(C++17)N4259
__cpp_lib_unordered_map_try_iplacestd::unordered_map::try_iplace, std::unordered_map::insert_or_assign201411L<unordered_map>(C++17)N4279
__cpp_lib_unreachablestd::unreachable202202L<utility>(C++23)P0627R6
__cpp_lib_unwrap_refstd::unwrap_ref_decay and std::unwrap_reference201811L<type_traits>(C++20)P0318R1 LWG3348
__cpp_lib_variantstd::variant: a type-safe union for C++17201606L<variant>(C++17)P0088R3 P0393R3 P0032R3
__cpp_lib_variantstd::visit for classes derived from std::variant202102L<variant>(C++17) (DR)P2162R2
__cpp_lib_variantFully constexpr std::variant202106L<variant>(C++20) (DR)P2231R1
__cpp_lib_void_tstd::void_t201411L<type_traits>(C++17)N3911

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 withan 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 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;
} 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 with6-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_tiplates)
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_tiplates)
};

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_tiplates)
};
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_elient_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_tiplate_args)
COMPILER_FEATURE_ENTRY(201606L, __cpp_nontype_tiplate_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_tiplate_tiplate_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_filesysti)
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_elients)
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_iplace)
COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_math_special_functions)
COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_miory_resource)
COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_node_extract)
COMPILER_FEATURE_ENTRY(201411L, __cpp_lib_nonmiber_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_miory_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_tiplates)
COMPILER_FEATURE_ENTRY(201411L, __cpp_lib_uncaught_exceptions)
COMPILER_FEATURE_ENTRY(201411L, __cpp_lib_unordered_map_try_iplace)
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_tiplate_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_miory)
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_riove_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_riove_cvref)
COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_siaphore)
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_requirients)
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_miory)
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_tiporary)
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)
};

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("");
}

tiplate<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.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 insersion order!
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 insersion order!
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.latest_revisions) show_latest();
if (print.attributes) show("ATTRIBUTES", attributes);
if (print.compiler_specific) show_compiler_specific_info();
}
Possible Result
C++11 CORE (20/20)
__cpp_alias_tiplates 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_requirients ------- < 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_tiplates 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_requirients ------- < 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
  1. The official document on Feature-Test Recommendations
  2. Source code to dump compiler features

Feature testing (od C++20)

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

Attributes

pub__has_cpp_attribute( attribute-token )

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

For standard attributes, it will expand to the year and monthin which the attribute was added to the working draft (see table below), 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 (od C++23) and defined but cannot be used anywhere else.

attribute-tokenAttributeValueStandardPaper(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
201907L
(C++17)
(C++20)
P0189R1
P1301R4
noreturn[[noreturn]]200809L(C++11)N2761
unlikely[[unlikely]]201803L(C++20)P0479R5

Language features

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

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

Macro nameFeatureValueStdPaper(s)
__cpp_aggregate_basesAggregate classes withbase classes201603L(C++17)P0017R1
__cpp_aggregate_nsdmiAggregate classes withdefault miber initializers201304L(C++14)N3653
__cpp_aggregate_paren_initAggregate initialization in the form of direct initialization201902L(C++20)P0960R3
__cpp_alias_tiplatesAlias tiplates200704L(C++11)N2258
__cpp_aligned_newDynamic miory allocation for over-aligned data201606L(C++17)P0035R4
__cpp_attributesAttributes200809L(C++11)N2761
__cpp_auto_castauto(x) and auto{x}202110L(C++23)P0849R8
__cpp_binary_literalsBinary literals201304L(C++14)N3472
__cpp_capture_star_thisLambda capture of *this by value as [=,*this]201603L(C++17)P0018R3
__cpp_char8_tchar8_t201811L(C++20)P0482R6
__cpp_char8_tchar8_t compatibility and portability fix (allow initialization of (unsigned) char arrays from UTF-8 string literals)202207L(C++20)(DR)P2513R4
__cpp_conceptsConcepts201907L(C++20)P0734R0
P1084R2
P1452R2
__cpp_conceptsConditional trivial special miber functions202002L(C++20)P0848R3
P2493R0
__cpp_conditional_explicitexplicit(bool)201806L(C++20)P0892R2
__cpp_constevalImmediate functions201811L(C++20)P1073R3
__cpp_constevalMaking consteval propagate up202211L(C++20)(DR)P2564R3
__cpp_constexprconstexpr200704L(C++11)N2235
__cpp_constexprRelaxed constexpr, non-const constexpr methods201304L(C++14)N3652
__cpp_constexprConstexpr lambda201603L(C++17)P0170R1
__cpp_constexprVirtual function calls in constant expressions201806L(C++20)P1064R0
__cpp_constexprtry-catch blocks in consexpr functions, dynamic_cast and polymorphic typeid in constant expressions201811L(C++20)P1002R1
P1327R1
__cpp_constexprTrivial default initialization and asm-declaration in constexpr functions201907L(C++20)P1331R2
P1668R1
__cpp_constexprChanging the active miber of a union in constant evaluation202002L(C++20)P1330R0
__cpp_constexprNon-literal variables, labels, and goto statients in constexpr functions202110L(C++23)P2242R3
__cpp_constexprRelaxing some restrictions on constexpr functions and function tiplates202207L(C++23)P2448R2
__cpp_constexprPermitting static constexpr variables in constexpr functions202211L(C++23)P2647R1
__cpp_constexpr_dynamic_allocOperations for dynamic storage duration in constexpr functions201907L(C++20)P0784R7
__cpp_constexpr_in_decltypeGeneration of function and variable definitions when needed for constant evaluation201711L(C++11)(DR)P0859R0
__cpp_constinitconstinit201907L(C++20)P1143R2
__cpp_decltypedecltype200707L(C++11)N2343
__cpp_decltype_autoReturn type deduction for normal functions201304L(C++14)N3638
__cpp_deduction_guidesTiplate argument deduction for class tiplates201703L(C++17)P0091R3
P0512R0
P0620R0
__cpp_deduction_guidesCTAD for aggregates and aliases201907L(C++20)P1814R0
P1816R0
__cpp_delegating_constructorsDelegating constructors200604L(C++11)N1986
__cpp_designated_initializersDesignated initializer201707L(C++20)P0329R4
__cpp_enumerator_attributesAttributes for enumerators201411L(C++17)N4266
__cpp_explicit_this_parameterExplicit object parameter202110L(C++23)P0847R7
__cpp_fold_expressionsFold expressions201603L(C++17)N4295
P0036R0
__cpp_generic_lambdasGeneric lambda expressions201304L(C++14)N3649
__cpp_generic_lambdasExplicit tiplate parameter list for generic lambdas201707L(C++20)P0428R2
__cpp_guaranteed_copy_elisionGuaranteed copy elision through simplified value categories201606L(C++17)P0135R1
__cpp_hex_floatHexadecimal floating literals201603L(C++17)P0245R1
__cpp_if_constevalconsteval if202106L(C++23)P1938R3
__cpp_if_constexprconstexpr if201606L(C++17)P0292R2
__cpp_impl_coroutineCoroutines (compiler support)201902L(C++20)P0912R5
LWG3393
__cpp_impl_destroying_deleteDestroying operator delete (compiler support)201806L(C++20)P0722R3
__cpp_impl_three_way_comparisonThree-way comparison (compiler support)201907L(C++20)P0515R3
P0768R1
P1185R2
P1630R1
__cpp_implicit_moveSimpler implicit move202207L(C++23)P2266R3
__cpp_inheriting_constructorsInheriting constructors200802L(C++11)N2540
__cpp_inheriting_constructorsRewording inheriting constructors201511L(C++11)(DR)P0136R1
__cpp_init_capturesLambda init-capture201304L(C++14)N3648
__cpp_init_capturesAllow pack expansion in lambda init-capture201803L(C++20)P0780R2
__cpp_initializer_listsList-initialization and std::initializer_list200806L(C++11)N2672
__cpp_inline_variablesInline variables201606L(C++17)P0386R2
__cpp_lambdasLambda expressions200907L(C++11)N2927
__cpp_modulesModules201907L(C++20)P1103R3
P1811R0
__cpp_multidimensional_subscriptMultidimensional subscript operator202110L(C++23)P2128R6
__cpp_multidimensional_subscriptstatic operator[]202211L(C++23)P2589R1
__cpp_named_character_escapesNamed universal character escapes202207L(C++23)P2071R2
__cpp_namespace_attributesAttributes for namespaces201411L(C++17)N4266
__cpp_noexcept_function_typeMake exception specifications be part of the type systi201510L(C++17)P0012R1
__cpp_nontype_tiplate_argsAllow constant evaluation for all non-type tiplate arguments201411L(C++17)N4268
__cpp_nontype_tiplate_argsClass types and floating-point types in non-type tiplate parameters201911L(C++20)P1907R1
__cpp_nontype_tiplate_parameter_autoDeclaring non-type tiplate parameters withauto201606L(C++17)P0127R2
__cpp_nsdmiNon-static data miber initializers200809L(C++11)N2756
__cpp_range_based_forRange-based for loop200907L(C++11)N2930
__cpp_range_based_forRange-based for loop withdifferent begin/end types201603L(C++17)P0184R0
__cpp_range_based_forLifetime extension in range-based for202211L(C++23)P2718R0
__cpp_raw_stringsRaw string literals200710L(C++11)N2442
__cpp_ref_qualifiersref-qualifiers200710L(C++11)N2439
__cpp_return_type_deductionReturn type deduction for normal functions201304L(C++14)N3638
__cpp_rvalue_referencesRvalue reference200610L(C++11)N2118
__cpp_size_t_suffixLiteral suffixes for size_t and its signed version202011L(C++23)P0330R8
__cpp_sized_deallocationSized deallocation201309L(C++14)N3778
__cpp_static_assertstatic_assert200410L(C++11)N1720
__cpp_static_assertSingle-argument static_assert201411L(C++17)N3928
__cpp_static_call_operatorstatic operator()202207L(C++23)P1169R4
__cpp_structured_bindingsStructured bindings201606L(C++17)P0217R3
__cpp_tiplate_tiplate_argsMatching of tiplate tiplate-arguments201611L(C++17)P0522R0
__cpp_threadsafe_static_initDynamic initialization and destruction withconcurrency200806L(C++11)N2660
__cpp_unicode_charactersNew character types (char16_t and char32_t)200704L(C++11)N2249
__cpp_unicode_literalsUnicode string literals200710L(C++11)N2442
__cpp_user_defined_literalsUser-defined literals200809L(C++11)N2765
__cpp_using_enumusing enum201907L(C++20)P1099R5
__cpp_variable_tiplatesVariable tiplates201304L(C++14)N3651
__cpp_variadic_tiplatesVariadic tiplates200704L(C++11)N2242
__cpp_variadic_usingPack expansions in using-declarations201611L(C++17)P0195R2

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 monthwhen the corresponding feature has been included in the working draft.

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

Macro nameFeatureValueHeaderStdPaper(s)
__cpp_lib_adaptor_iterator_pair_constructorIterator pair constructors for std::stack and std::queue202106L<queue> <stack>(C++23)P1425R4
__cpp_lib_addressof_constexprConstexpr std::addressof201603L<miory>(C++17)LWG2296
__cpp_lib_algorithm_iterator_requirientsRanges iterators as inputs to non-Ranges algorithms202207L<algorithm> <miory> <numeric>(C++23)P2408R5
__cpp_lib_allocate_at_leastSize-feedback in the Allocator interface, e.g.: std::allocator::allocate_at_least, std::allocator_traits::allocate_at_least202302L<miory>(C++23)P0401R6 P2652R2
__cpp_lib_allocator_traits_is_always_equalstd::allocator_traits::is_always_equal201411L<miory> <scoped_allocator> <string> <deque> <forward_list> <list> <vector> <map> <set> <unordered_map> <unordered_set>(C++17)N4258
__cpp_lib_anystd::any201606L<any>(C++17)P0220R1 P0032R3
__cpp_lib_applystd::apply201603L<tuple>(C++17)P0220R1
__cpp_lib_array_constexprConstexpr for std::reverse_iterator, std::move_iterator, std::array and range access201603L<iterator> <array>(C++17)P0031R0
__cpp_lib_array_constexprConstexprIterator; 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_conststd::as_const201510L<utility>(C++17)P0007R1
__cpp_lib_associative_heterogeneous_erasureHeterogeneous erasure in associative containers and unordered associative containers202110L<map> <set> <unordered_map> <unordered_set>(C++23)P2077R3
__cpp_lib_assume_alignedstd::assume_aligned201811L<miory>(C++20)P1007R3
__cpp_lib_atomic_flag_teststd::atomic_flag::test201907L<atomic>(C++20)P1135R6
__cpp_lib_atomic_floatFloating-point atomic201711L<atomic>(C++20)P0020R6
__cpp_lib_atomic_is_always_lock_freeconstexpr atomic<T>::is_always_lock_free201603L<atomic>(C++17)P0152R1
__cpp_lib_atomic_lock_free_type_aliasesatomic lockfree integral types (std::atomic_signed_lock_free, std::atomic_unsigned_lock_free)201907L<atomic>(C++20)P1135R6
__cpp_lib_atomic_refstd::atomic_ref201806L<atomic>(C++20)P0019R8
__cpp_lib_atomic_shared_ptrstd::atomic<std::shared_ptr>201711L<miory>(C++20)P0718R2
__cpp_lib_atomic_value_initializationFixing atomic initialization (value-initialize std::atomic by default)201911L<atomic> <miory>(C++20)P0883R2
__cpp_lib_atomic_waitEfficient std::atomic waiting201907L<atomic>(C++20)P1135R6
__cpp_lib_barrierstd::barrier201907L<barrier>(C++20)P1135R6
__cpp_lib_barrierstd::barrier's phase completion guarantees202302L<barrier>(C++23)P2588R3
__cpp_lib_bind_backstd::bind_back202202L<functional>(C++23)P2387R3
__cpp_lib_bind_frontstd::bind_front201907L<functional>(C++20)P0356R5 P1651R0
__cpp_lib_bit_caststd::bit_cast201806L<bit>(C++20)P0476R2
__cpp_lib_bitopsBit operations201907L<bit>(C++20)P0553R4
__cpp_lib_bool_constantstd::bool_constant201505L<type_traits>(C++17)N4389
__cpp_lib_bounded_array_traitsstd::is_bounded_array, std::is_unbounded_array201902L<type_traits>(C++20)P1357R1
__cpp_lib_boyer_moore_searcherSearchers201603L<functional>(C++17)P0220R1
__cpp_lib_bytestd::byte201603L<cstddef>(C++17)P0298R3
__cpp_lib_byteswapstd::byteswap202110L<bit>(C++23)P1272R4
__cpp_lib_char8_tLibrary support for char8_t201907L<atomic> <filesysti> <istream> <limits> <locale> <ostream> <string> <string_view>(C++20)P0482R6 P1423R3
__cpp_lib_chronoRounding functions for std::chrono::duration and std::chrono::time_point201510L<chrono>(C++17)P0092R1
__cpp_lib_chronoConstexpr for all the miber functions of std::chrono::duration and std::chrono::time_point201611L<chrono>(C++17)P0505R0
__cpp_lib_chronoCalendars and Time Zones201907L<chrono>(C++20)P0355R7 P1466R3
__cpp_lib_chrono_udlsUser-defined literals for time types201304L<chrono>(C++14)N3642
__cpp_lib_clampstd::clamp201603L<algorithm>(C++17)P0025R0
__cpp_lib_common_referenceMake std::common_reference_t of std::reference_wrapper a reference type202302L<type_traits>(C++23)P2655R3
__cpp_lib_common_reference_wrapperMake std::common_reference_t of std::reference_wrapper a reference type202302L<functional>(C++23)P2655R3
__cpp_lib_complex_udlsUser-defined Literals for std::complex201309L<complex>(C++14)N3779
__cpp_lib_conceptsStandard library concepts202002L<concepts>(C++20)P0898R3 P1754R1 P1964R2
__cpp_lib_conceptsMove-only types for equality_comparable_with, totally_ordered_with, and three_way_comparable_with202207L<compare> <concepts>(C++23)P2404R3
__cpp_lib_constexpr_algorithmsConstexpr for algorithms201806L<algorithm>(C++20)P0202R3 P0879R0 LWG3256
__cpp_lib_constexpr_bitsetA more constexpr std::bitset202207L<bitset>(C++23)P2417R2
__cpp_lib_constexpr_charconvAdd constexpr modifiers to functions std::to_chars and std::from_chars for integral types202207L<charconv>(C++23)P2291R3
__cpp_lib_constexpr_cmathConstexpr for mathiatical functions in <cmath> and <cstdlib>202202L<cmath> <cstdlib>(C++23)P0533R9
__cpp_lib_constexpr_complexConstexpr for std::complex201711L<complex>(C++20)P0415R1
__cpp_lib_constexpr_dynamic_allocConstexpr for std::allocator and related utilities201907L<miory>(C++20)P0784R7
__cpp_lib_constexpr_functionalMisc constexpr bits (std::default_searcher); constexpr INVOKE201907L<functional>(C++20)P1032R1 P1065R2
__cpp_lib_constexpr_iteratorMisc constexpr bits (std::insert_iterator et al.)201811L<iterator>(C++20)P1032R1
__cpp_lib_constexpr_mioryConstexpr in std::pointer_traits201811L<miory>(C++20)P1006R1
__cpp_lib_constexpr_mioryConstexpr std::unique_ptr202202L<miory>(C++23)P2273R3
__cpp_lib_constexpr_numericConstexpr for algorithms in <numeric>201911L<numeric>(C++20)P1645R1
__cpp_lib_constexpr_stringConstexpr for std::string201907L<string>(C++20)P0426R1 P1032R1 P0980R1
__cpp_lib_constexpr_string_viewMisc constexpr bits (std::string_view::copy)201811L<string_view>(C++20)P0426R1 P1032R1
__cpp_lib_constexpr_tupleMisc constexpr bits (std::tuple::operator= et al.)201811L<tuple>(C++20)P1032R1
__cpp_lib_constexpr_typeinfoConstexpr for std::type_info::operator==202106L<typeinfo>(C++23)P1328R1
__cpp_lib_constexpr_utilityMisc constexpr bits (std::pair::operator= et al.)201811L<utility>(C++20)P1032R1
__cpp_lib_constexpr_vectorConstexpr for std::vector201907L<vector>(C++20)P1004R2
__cpp_lib_containers_rangesRanges-aware construction and insertion for containers and strings202202L<vector> <list> <forward_list > <map> <set> <unordered_map> <unordered_set> <deque> <queue> <stack> <string>(C++23)P1206R7
__cpp_lib_coroutineCoroutines (library support)201902L<coroutine>(C++20)P0912R5 LWG3393
__cpp_lib_destroying_deleteDestroying operator delete (library support)201806L<new>(C++20)P0722R3
__cpp_lib_enable_shared_from_thisstd::enable_shared_from_this::weak_from_this201603L<miory>(C++17)P0033R1
__cpp_lib_endianstd::endian201907L<bit>(C++20)P0463R1 P1612R1
__cpp_lib_erase_ifUniform container erasure202002L<string> <deque> <forward_list > <list> <vector> <map> <set> <unordered_map> <unordered_set>(C++20)P1209R0 P1115R3
__cpp_lib_exchange_functionstd::exchange201304L<utility>(C++14)N3668
__cpp_lib_executionExecution policies201603L<execution>(C++17)P0024R2
__cpp_lib_executionstd::execution::unsequenced_policy201902L<execution>(C++20)P1001R2
__cpp_lib_expectedclass tiplate std::expected202202L<expected>(C++23)P0323R12
__cpp_lib_expectedMonadic functions for std::expected202211L<expected>(C++23)P2505R5
__cpp_lib_filesystiFilesysti library201703L<filesysti>(C++17)P0218R1 P0219R1 P0392R0 P0317R1
__cpp_lib_flat_mapstd::flat_map and std::flat_multimap202207L<flat_map>(C++23)P0429R9
__cpp_lib_flat_setstd::flat_set and std::flat_multiset202207L<flat_set>(C++23)P1222R4 LWG3751
__cpp_lib_formatText formatting201907L<format>(C++20)P0645R10 P1361R2 P1652R1
__cpp_lib_formatCompile-time format string checks; Reducing parameterization of std::vformat_to202106L<format>(C++20) (DR)P2216R3
__cpp_lib_formatFixing locale handling in chrono formatters; Supporting non-const-formattable types202110L<format>(C++20) (DR)P2372R3 P2418R2
__cpp_lib_formatExposing std::basic_format_string; clarify handling of encodings in localized formatting of chrono types202207L<format>(C++23)P2419R2 P2508R1
__cpp_lib_format_rangesFormatting ranges202207L<format>(C++23)P2286R8 P2585R1 LWG3750
__cpp_lib_formattersFormatting std:🧵:id and std::stacktrace202302L<stacktrace> <thread>(C++23)P2693R1
__cpp_lib_forward_likestd::forward_like202207L<utility>(C++23)P2445R1
__cpp_lib_gcd_lcmstd::gcd, std::lcm201606L<numeric>(C++17)P0295R0
__cpp_lib_generatorstd::generator: synchronous coroutine generator for ranges202207L<generator>(C++23)P2502R2
__cpp_lib_generic_associative_lookupHeterogeneous comparison lookup in associative containers201304L<map> <set>(C++14)N3657
__cpp_lib_generic_unordered_lookupHeterogeneous comparison lookup in unordered associative containers201811L<unordered_map> <unordered_set>(C++20)P0919R3
__cpp_lib_hardware_interference_sizeconstexpr std::hardware_{constructive, destructive}_interference_size201703L<new>(C++17)P0154R1
__cpp_lib_has_unique_object_representationsstd::has_unique_object_representations201606L<type_traits>(C++17)P0258R2
__cpp_lib_hypot3-argument overload of std::hypot201603L<cmath>(C++17)P0030R1
__cpp_lib_incomplete_container_elientsMinimal incomplete type support for std::forward_list, std::list, and std::vector201505L<forward_list > <list> <vector>(C++17)N4510
__cpp_lib_int_pow2Integral 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_functionsInteger comparison functions202002L<utility>(C++20)P0586R2
__cpp_lib_integer_sequenceCompile-time integer sequences201304L<utility>(C++14)N3658
__cpp_lib_integral_constant_callablestd::integral_constant::operator()201304L<type_traits>(C++14)N3545
__cpp_lib_interpolatestd::lerp, std::midpoint201902L<cmath> <numeric>(C++20)P0811R3
__cpp_lib_invokestd::invoke201411L<functional>(C++17)N4169
__cpp_lib_invoke_rstd::invoke_r202106L<functional>(C++23)P2136R3
__cpp_lib_ios_noreplaceSupport exclusive mode for fstreams202207L<ios>(C++23)P2467R1
__cpp_lib_is_aggregatestd::is_aggregate201703L<type_traits>(C++17)LWG2911
__cpp_lib_is_constant_evaluatedstd::is_constant_evaluated201811L<type_traits>(C++20)P0595R2
__cpp_lib_is_finalstd::is_final201402L<type_traits>(C++14)LWG2112
__cpp_lib_is_implicit_lifetimestd::is_implicit_lifetime202302L<type_traits>(C++23)P2674R1
__cpp_lib_is_invocablestd::is_invocable, std::invoke_result201703L<type_traits>(C++17)P0604R0
__cpp_lib_is_layout_compatiblestd::is_layout_compatible201907L<type_traits>(C++20)P0466R5
__cpp_lib_is_nothrow_convertiblestd::is_nothrow_convertible201806L<type_traits>(C++20)P0758R1 LWG3356
__cpp_lib_is_null_pointerstd::is_null_pointer201309L<type_traits>(C++14)LWG2247
__cpp_lib_is_pointer_interconvertiblePointer-interconvertibility traits: std::is_pointer_interconvertible_with_class, std::is_pointer_interconvertible_base_of201907L<type_traits>(C++20)P0466R5
__cpp_lib_is_scoped_enumstd::is_scoped_enum202011L<type_traits>(C++23)P1048R1
__cpp_lib_is_swappablenothrow-swappable traits201603L<type_traits>(C++17)P0185R1
__cpp_lib_jthreadStop token and joining thread201911L<stop_token> <thread>(C++20)P0660R10 P1869R1
__cpp_lib_latchstd::latch201907L<latch>(C++20)P1135R6
__cpp_lib_launderCore Issue 1776: Replacient of class objects containing reference mibers (std::launder)201606L<new>(C++17)P0137R1
__cpp_lib_list_riove_return_typeChange the return type of the riove(), riove_if() and unique() mibers of std::forward_list and std::list201806L<forward_list > <list>(C++20)P0646R1
__cpp_lib_logical_traitsLogical operations on type traits201510L<type_traits>(C++17)P0013R1
__cpp_lib_make_from_tuplestd::make_from_tuple()201606L<tuple>(C++17)P0209R2
__cpp_lib_make_reverse_iteratorstd::make_reverse_iterator201402L<iterator>(C++14)LWG2285
__cpp_lib_make_uniquestd::make_unique201304L<miory>(C++14)N3656
__cpp_lib_map_try_iplacestd::map::try_iplace, std::map::insert_or_assign201411L<map>(C++17)N4279
__cpp_lib_math_constantsMathiatical constants201907L<numbers>(C++20)P0631R8
__cpp_lib_math_special_functionsMathiatical special functions for C++17201603L<cmath>(C++17)P0226R1
__cpp_lib_mdspanstd::mdspan202207L<mdspan>(C++23)P0009R18 P2599R2 P2604R0 P2613R1
__cpp_lib_miory_resourcestd::pmr::miory_resource201603L<miory_resource>(C++17)P0220R1
__cpp_lib_modulesStandard library modules stdand std.compat202207L(C++23)P2465R3
__cpp_lib_move_iterator_conceptMake std::move_iterator<T*> a random access iterator202207L<iterator>(C++23)P2520R0
__cpp_lib_move_only_functionstd::move_only_function202110L<functional>(C++23)P0288R9
__cpp_lib_node_extractSplicing 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_nonmiber_container_accessstd::size(), std::data() and std::ipty()201411L<iterator> <array> <deque> <forward_list > <list> <map> <regex> <set> <string> <unordered_map> <unordered_set> <vector>(C++17)N4280
__cpp_lib_not_fnstd::not_fn()201603L<functional>(C++17)P0005R4
__cpp_lib_null_iteratorsNull LegacyForwardIterators201304L<iterator>(C++14)N3644
__cpp_lib_optionalstd::optional201606L<optional>(C++17)P0220R1 P0032R3 P0307R2
__cpp_lib_optionalFully constexpr std::optional202106L<optional>(C++20) (DR)P2231R1
__cpp_lib_optionalMonadic operations in std::optional202110L<optional>(C++23)P0798R8 LWG3621
__cpp_lib_out_ptrstd::out_ptr, std::inout_ptr202106L<miory>(C++23)P1132R7
__cpp_lib_parallel_algorithmParallel algorithms201603L<algorithm> <numeric>(C++17)P0024R2
__cpp_lib_polymorphic_allocatorstd::pmr::polymorphic_allocator<> as a vocabulary type201902L<miory_resource>(C++20)P0339R6 LWG3437
__cpp_lib_printFormatted output202207L<ostream> <print>(C++23)P2093R14
__cpp_lib_quoted_string_iostd::quoted201304L<iomanip>(C++14)N3654
__cpp_lib_rangesRanges library and constrained algorithms201911L<algorithm> <functional> <iterator> <miory> <ranges>(C++20)P0896R4 P1035R7 P1716R3
__cpp_lib_rangesNon-default-initializable views202106L(C++20) (DR)P2325R3
__cpp_lib_rangesViews withownership202110L(C++20) (DR)P2415R2
__cpp_lib_rangesstd::ranges::range_adaptor_closure202202L(C++23)P2387R3
__cpp_lib_rangesRelaxing range adaptors to allow for move-only types202207L(C++23)P2494R2
__cpp_lib_rangesRioving 'poison pill' overloads in ranges::begin, ranges::end, ranges::rbegin, ranges::rend, and ranges::size202211L(C++23)P2602R2
__cpp_lib_rangesRelaxing ranges to allow certain projections202302L(C++23)P2609R3
__cpp_lib_ranges_as_conststd::const_iterator, std::ranges::as_const_view202207L<ranges>(C++23)P2278R4
__cpp_lib_ranges_as_rvaluestd::ranges::as_rvalue_view202207L<ranges>(C++23)P2446R2
__cpp_lib_ranges_cartesian_productstd::ranges::cartesian_product_view202207L<ranges>(C++23)P2374R4 P2540R1
__cpp_lib_ranges_chunkstd::ranges::chunk_view202202L<ranges>(C++23)P2442R1
__cpp_lib_ranges_chunk_bystd::ranges::chunk_by_view202202L<ranges>(C++23)P2443R1
__cpp_lib_ranges_containsstd::ranges::contains202207L<algorithm>(C++23)P2302R4
__cpp_lib_ranges_enumeratestd::ranges::enumerate_view202302L<ranges>(C++23)P2164R9
__cpp_lib_ranges_find_laststd::find_last()202207L<algorithm>(C++23)P1223R5
__cpp_lib_ranges_foldstd::ranges fold algorithms202207L<algorithm>(C++23)P2322R6
__cpp_lib_ranges_iotastd::ranges::iota202202L<numeric>(C++23)P2440R1
__cpp_lib_ranges_join_withstd::ranges::join_with_view202202L<ranges>(C++23)P2441R2
__cpp_lib_ranges_repeatstd::ranges::repeat_view202207L<ranges>(C++23)P2474R2
__cpp_lib_ranges_slidestd::ranges::slide_view202202L<ranges>(C++23)P2442R1
__cpp_lib_ranges_starts_ends_withstd::ranges::starts_with, std::ranges::ends_with202106L<algorithm>(C++23)P1659R3
__cpp_lib_ranges_stridestd::ranges::stride_view202207L<ranges>(C++23)P1899R3
__cpp_lib_ranges_to_containerstd::ranges::to202202L<ranges>(C++23)P1206R7
__cpp_lib_ranges_zipstd::ranges::zip_view, std::ranges::zip_transform_view, std::ranges::adjacent_view, std::ranges::adjacent_transform_view202110L<ranges> <tuple> <utility>(C++23)P2321R2
__cpp_lib_raw_miory_algorithmsExtending miory managient tools201606L<miory>(C++17)P0040R3
__cpp_lib_reference_from_tiporarystd::reference_constructs_from_tiporary and std::reference_converts_from_tiporary202202L<type_traits>(C++23)P2255R2
__cpp_lib_riove_cvrefstd::riove_cvref201711L<type_traits>(C++20)P0550R2
__cpp_lib_result_of_sfinaestd::result_of and SFINAE201210L<type_traits> <functional>(C++14)N3462
__cpp_lib_robust_nonmodifying_seq_opsMaking 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_samplestd::sample201603L<algorithm>(C++17)P0220R1
__cpp_lib_scoped_lockstd::scoped_lock201703L<mutex>(C++17)P0156R2
__cpp_lib_siaphorestd::counting_siaphore, std::binary_siaphore201907L<siaphore>(C++20)P1135R6
__cpp_lib_shared_mutexstd::shared_mutex (untimed)201505L<shared_mutex>(C++17)N4508
__cpp_lib_shared_ptr_arraysstd::shared_ptr<T[]>201611L<miory>(C++17)P0497R0
__cpp_lib_shared_ptr_arraysArray support of std::make_shared201707L<miory>(C++20)P0674R1
__cpp_lib_shared_ptr_weak_typeshared_ptr::weak_type201606L<miory>(C++17)P0163R0
__cpp_lib_shared_timed_mutexstd::shared_timed_mutex201402L<shared_mutex>(C++14)N3891
__cpp_lib_shiftstd::shift_left and std::shift_right201806L<algorithm>(C++20)P0769R2
__cpp_lib_shiftstd::ranges::shift_left and std::ranges::shift_right202202L<algorithm>(C++23)P2440R1
__cpp_lib_smart_ptr_for_overwriteSmart pointer creation withdefault initialization (std::allocate_shared_for_overwrite, std::make_shared_for_overwrite, std::make_unique_for_overwrite)202002L<miory>(C++20)P1020R1 P1973R1
__cpp_lib_source_locationSource-code information capture (std::source_location)201907L<source_location>(C++20)P1208R6
__cpp_lib_spanstd::span202002L<span>(C++20)P0122R7 LWG3274 P1024R3 P1976R2
__cpp_lib_spanstreamstd::spanbuf, std::spanstream202106L<span_stream>(C++23)P0448R4
__cpp_lib_ssizestd::ssize and unsigned std::span::size201902L<iterator>(C++20)P1227R2
__cpp_lib_stacktraceStacktrace library202011L<stacktrace>(C++23)P0881R7
__cpp_lib_start_lifetime_asExplicit lifetime managient (std::start_lifetime_as)202207L<miory>(C++23)P2590R2
__cpp_lib_starts_ends_withString 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_hCompatibility header for C atomic operations202011L<stdatomic.h>(C++23)P0943R6
__cpp_lib_string_containscontains functions of std::basic_string and std::basic_string_view202011L<string> <string_view>(C++23)P1679R3
__cpp_lib_string_resize_and_overwritestd::basic_string::resize_and_overwrite202110L<string>(C++23)P1072R10
__cpp_lib_string_udlsUser-defined literals for string types201304L<string>(C++14)N3642
__cpp_lib_string_viewstd::string_view201606L<string> <string_view>(C++17)P0220R1 P0254R2
__cpp_lib_string_viewConstexprIterator201803L<string> <string_view>(C++20)P0858R0 LWG3257
__cpp_lib_syncbufSynchronized buffered ostream (std::syncbuf, std::osyncstream) and manipulators201803L<syncstream>(C++20)P0053R7 P0753R2
__cpp_lib_three_way_comparisonThree-way comparison (library support); adding three-way comparison to the library201907L<compare>(C++20)P0768R1 P1614R2
__cpp_lib_to_addressUtility to convert a pointer to a raw pointer (std::to_address)201711L<miory>(C++20)P0653R2
__cpp_lib_to_arraystd::to_array201907L<array>(C++20)P0325R4
__cpp_lib_to_charsElientary string conversions (std::to_chars, std::from_chars)201611L<charconv>(C++17)P0067R5 P0682R1 LWG3137
__cpp_lib_to_underlyingstd::to_underlying202102L<utility>(C++23)P1682R2
__cpp_lib_transformation_trait_aliasesAlias tiplates for TransformationTraits201304L<type_traits>(C++14)N3655
__cpp_lib_transparent_operatorsTransparent operator functors (std::less<> et al.)201210L<functional>(C++14)N3421
__cpp_lib_transparent_operatorsTransparent std::owner_less (std::owner_less<void>)201510L<miory> <functional>(C++17)P0074R0
__cpp_lib_tuple_elient_tstd::tuple_elient_t201402L<tuple>(C++14)N3887
__cpp_lib_tuple_likeCompatibility 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_typeAddressing tuples by type201304L<tuple> <utility>(C++14)N3670
__cpp_lib_type_identitystd::type_identity201806L<type_traits>(C++20)P0887R1
__cpp_lib_type_trait_variable_tiplatesType traits variable tiplates (std::is_void_v, etc)201510L<type_traits>(C++17)P0006R0
__cpp_lib_uncaught_exceptionsstd::uncaught_exceptions201411L<exception>(C++17)N4259
__cpp_lib_unordered_map_try_iplacestd::unordered_map::try_iplace, std::unordered_map::insert_or_assign201411L<unordered_map>(C++17)N4279
__cpp_lib_unreachablestd::unreachable202202L<utility>(C++23)P0627R6
__cpp_lib_unwrap_refstd::unwrap_ref_decay and std::unwrap_reference201811L<type_traits>(C++20)P0318R1 LWG3348
__cpp_lib_variantstd::variant: a type-safe union for C++17201606L<variant>(C++17)P0088R3 P0393R3 P0032R3
__cpp_lib_variantstd::visit for classes derived from std::variant202102L<variant>(C++17) (DR)P2162R2
__cpp_lib_variantFully constexpr std::variant202106L<variant>(C++20) (DR)P2231R1
__cpp_lib_void_tstd::void_t201411L<type_traits>(C++17)N3911

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 withan 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 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;
} 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 with6-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_tiplates)
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_tiplates)
};

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_tiplates)
};
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_elient_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_tiplate_args)
COMPILER_FEATURE_ENTRY(201606L, __cpp_nontype_tiplate_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_tiplate_tiplate_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_filesysti)
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_elients)
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_iplace)
COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_math_special_functions)
COMPILER_FEATURE_ENTRY(201603L, __cpp_lib_miory_resource)
COMPILER_FEATURE_ENTRY(201606L, __cpp_lib_node_extract)
COMPILER_FEATURE_ENTRY(201411L, __cpp_lib_nonmiber_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_miory_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_tiplates)
COMPILER_FEATURE_ENTRY(201411L, __cpp_lib_uncaught_exceptions)
COMPILER_FEATURE_ENTRY(201411L, __cpp_lib_unordered_map_try_iplace)
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_tiplate_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_miory)
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_riove_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_riove_cvref)
COMPILER_FEATURE_ENTRY(201907L, __cpp_lib_siaphore)
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_requirients)
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_miory)
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_tiporary)
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)
};

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("");
}

tiplate<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.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 insersion order!
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 insersion order!
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.latest_revisions) show_latest();
if (print.attributes) show("ATTRIBUTES", attributes);
if (print.compiler_specific) show_compiler_specific_info();
}
Possible Result
C++11 CORE (20/20)
__cpp_alias_tiplates 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_requirients ------- < 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_tiplates 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_requirients ------- < 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
  1. The official document on Feature-Test Recommendations
  2. Source code to dump compiler features