功能特性测试 (C++20)

来自cppreference.com
< cpp


标准中为 C++11 和之后引入的 C++ 语言和程序库的功能特性定义了一组预处理器宏。标准有意使之成为检测这些功能特性是否存在的一种简单且可移植的方式。

属性

__has_cpp_attribute( 属性记号 )

检查是否支持(宏展开后)属性记号 指名的属性

对于每个标准属性,__has_cpp_attribute 会展开成下表中的对应值(它是该属性被添加到工作草案中时的年份和月份)还是 0 由实现定义。它只会在此标准属性能够使得实现的行为遵循推荐要求时(包括发布诊断信息和改变类布局等各类行为)展开成下表中的对应值。

厂商特定的属性会以某个非零值确定。

可以在 #if #elif 的表达式中展开 __has_cpp_attribute #ifdef #ifndef #elifdef #elifndef(C++23 起)defined 把它当做已定义的宏,但不能在别处使用它。

属性记号属性标准标准文件
assume[[assume]]202207L(C++23)P1774R8
carries_dependency[[carries_dependency]]200809L(C++11)
(C++26 前)
N2556
N2643
P3475R2
deprecated[[deprecated]]201309L(C++14)N3760
fallthrough[[fallthrough]]201603L(C++17)P0188R1
indeterminate[[indeterminate]]202403L(C++26)P2795R5
likely[[likely]]201803L(C++20)P0479R5
maybe_unused[[maybe_unused]]201603L(C++17)P0212R1
no_unique_address[[no_unique_address]]201803L(C++20)P0840R2
nodiscard[[nodiscard]]201603L(C++17)P0189R1
给出理由的 [[nodiscard]]201907L(C++20)P1301R4
noreturn[[noreturn]]200809L(C++11)N2761
unlikely[[unlikely]]201803L(C++20)P0479R5
属性总数:11

语言功能特性

下列宏可以用来检测当前实现是否实现了某个语言功能特性。它们会在每个翻译单元预定义

每个宏都会展开成对应于相应功能特性被包含到工作草案时的年份与月份的整数字面量。当功能特性发生了显著变更时,宏会相应地更新。

宏名功能特性标准标准文件
__cpp_aggregate_bases拥有基类的聚合类201603L(C++17)P0017R1
__cpp_aggregate_nsdmi拥有默认成员初始化器聚合类201304L(C++14)N3653
__cpp_aggregate_paren_init具有直接初始化形式的聚合初始化201902L(C++20)P0960R3
__cpp_alias_templates别名模版200704L(C++11)N2258
__cpp_aligned_new过对齐数据的动态内存分配201606L(C++17)P0035R4
__cpp_attributes属性200809L(C++11)N2761
__cpp_auto_castauto(x)auto{x}202110L(C++23)P0849R8
__cpp_binary_literals二进制字面量201304L(C++14)N3472
__cpp_capture_star_this[=,*this] 进行 *this 的 lambda 按值捕获201603L(C++17)P0018R3
__cpp_char8_tchar8_t201811L(C++20)P0482R6
char8_t 兼容性和可移植性修复(允许从 UTF-8 字符串字面量初始化(无符号)字符数组202207L(C++23)
(DR20)
P2513R4
__cpp_concepts概念201907L(C++20)P0734R0
P1084R2
P1452R2
按条件平凡的特殊成员函数202002LP0848R3
P2493R0
__cpp_conditional_explicitexplicit(bool)201806L(C++20)P0892R2
__cpp_consteval立即函数201811L(C++20)P1073R3
使 consteval 向上传播202211L(C++23)
(DR20)
P2564R3
__cpp_constexprconstexpr200704L(C++11)N2235
放宽 constexpr 限制constconstexpr 方法201304L(C++14)N3652
constexpr 的 lambda201603L(C++17)P0170R1
在常量表达式中调用虚函数constexpr 函数中的 try,常量表达式中的 dynamic_cast 和多态 typeidconstexpr 函数中的平凡默认初始化汇编声明201907L(C++20)P1064R0
P1002R1
P1327R1
P1331R2
P1668R1
在常量求值中改变联合体的活跃成员202002LP1330R0
P2493R0
constexpr 函数中的非字面变量、标号和 goto 语句202110L(C++23)P2242R3
放松对 constexpr 函数和函数模板的一些限制202207LP2448R2
constexpr 函数中允许静态 constexpr 变量202211LP2647R1
void* 进行 constexpr 转换:走向 constexpr 类型擦除202306L(C++26)P2738R1
constexpr 布置 new202406LP2747R2
__cpp_constexpr_dynamic_allocconstexpr 函数中的动态存储期操作201907L(C++20)P0784R7
__cpp_constexpr_exceptionsconstexpr 异常202411L(C++26)P3068R6
__cpp_constexpr_in_decltype在为常量求值所需要时生成函数和变量的定义201711L(C++20)
(DR11)
P0859R0
__cpp_constinitconstinit201907L(C++20)P1143R2
__cpp_contracts契约202502L(C++26)P2900R14
__cpp_decltypedecltype200707L(C++11)N2343
__cpp_decltype_auto常规函数的返回类型推导201304L(C++14)N3638
__cpp_deduction_guides类模板的模板实参推导(CTAD)201703L(C++17)P0091R3
P0512R0
P0620R0
聚合体与别名的 CTAD201907L(C++20)P1814R0
P1816R0
__cpp_delegating_constructors委托构造函数200604L(C++11)N1986
__cpp_deleted_function带消息的弃置函数定义= delete("应给出理由");202403L(C++26)P2573R2
__cpp_designated_initializers指派初始化器201707L(C++20)P0329R4
__cpp_enumerator_attributes枚举项的属性201411L(C++17)N4266
__cpp_explicit_this_parameter显式对象形参202110L(C++23)P0847R7
__cpp_fold_expressions折叠表达式201603L(C++17)N4295
P0036R0
涉及折叠表达式约束的排序202406L(C++26)P2963R3
__cpp_generic_lambdas泛型 lambda 表达式201304L(C++14)N3649
泛型 lambda 的显式模板形参列表201707L(C++20)P0428R2
__cpp_guaranteed_copy_elision通过简化的值类别保证复制消除201606L(C++17)P0135R1
__cpp_hex_float十六进制浮点字面量201603L(C++17)P0245R1
__cpp_if_constevalif consteval202106L(C++23)P1938R3
__cpp_if_constexprif constexpr201606L(C++17)P0292R2
__cpp_impl_coroutine协程(编译器支持)201902L(C++20)P0912R5
LWG3393
__cpp_impl_destroying_delete销毁的 operator delete(编译器支持)201806L(C++20)P0722R3
__cpp_impl_three_way_comparison三路比较(编译器支持)201907L(C++20)P0515R3
P0768R1
P1185R2
P1630R1
__cpp_implicit_move简化的隐式移动202207L(C++23)P2266R3
__cpp_inheriting_constructors继承构造函数200802L(C++11)N2540
重述继承构造函数:有关继承构造函数的信规范(DR1941 等)201511L(C++17)
(DR11)
P0136R1
__cpp_init_captureslambda 的初始化捕获201304L(C++14)N3648
允许 lambda 初始化捕获中的包展开201803L(C++20)P0780R2
__cpp_initializer_lists列表初始化std::initializer_list200806L(C++11)N2672
__cpp_inline_variables内联变量201606L(C++17)P0386R2
__cpp_lambdaslambda 表达式200907L(C++11)N2927
__cpp_modules模块201907L(C++20)P1103R3
P1811R0
__cpp_multidimensional_subscript多维下标运算符202110L(C++23)P2128R6
静态的 operator[]202211LP2589R1
__cpp_named_character_escapes具名的通用字符转义202207L(C++23)P2071R2
__cpp_namespace_attributes命名空间的属性201411L(C++17)N4266
__cpp_noexcept_function_type使异常说明为类型系统的一部分201510L(C++17)P0012R1
__cpp_nontype_template_args允许全部非类型模板实参的常量求值201411L(C++17)N4268
非类型模板形参中的类类型与浮点类型201911L(C++20)P1907R1
__cpp_nontype_template_parameter_autoauto 声明非类型模板形参201606L(C++17)P0127R2
__cpp_nsdmi非静态数据成员初始化器200809L(C++11)N2756
__cpp_pack_indexing包索引202311L(C++26)P2662R3
__cpp_placeholder_variables好用的无名占位符202306L(C++26)P2169R4
__cpp_pp_embed #embed202502L(C++26)P1967R14
__cpp_range_based_for基于范围的 for 循环200907L(C++11)N2930
拥有不同类型的 begin/end基于范围的 for 循环201603L(C++17)P0184R0
基于范围的 for 循环的生存期延长202211L(C++23)P2644R1
P2718R0
CWG2659
__cpp_raw_strings原始字符串字面量200710L(C++11)N2442
__cpp_ref_qualifiers引用限定符200710L(C++11)N2439
__cpp_return_type_deduction常规函数的返回类型推导201304L(C++14)N3638
__cpp_rvalue_references右值引用200610L(C++11)N2118
__cpp_size_t_suffixstd::size_t 以及它的有符号版本的字面量后缀202011L(C++23)P0330R8
__cpp_sized_deallocation具有大小的解分配函数201309L(C++14)N3778
__cpp_static_assertstatic_assert200410L(C++11)N1720
单参数的 static_assert201411L(C++17)N3928
用户生成的 static_assert 消息202306L(C++26)P2741R3
__cpp_static_call_operator静态的 operator()202207L(C++23)P1169R4
__cpp_structured_bindings结构化绑定201606L(C++17)P0217R3
结构化绑定属性202403L(C++26)P0609R3
结构化绑定声明为条件202406LP0963R3
结构化绑定可以引入202411LP1061R10
__cpp_template_parameters概念和变量模板为模板形参202502L(C++26)P2841R7
__cpp_template_template_args模板模板实参的匹配201611L(C++17)P0522R0
__cpp_threadsafe_static_init并发的动态初始化和销毁200806L(C++11)N2660
__cpp_trivial_relocatability可平凡重定位性202502L(C++26)P2786R13
__cpp_trivial_union平凡联合体202502L(C++26)P3074R7
__cpp_unicode_characters新字符类型char16_tchar32_t200704L(C++11)N2249
__cpp_unicode_literalsUnicode 字符串字面量200710L(C++11)N2442
__cpp_user_defined_literals用户定义字面量200809L(C++11)N2765
__cpp_using_enumusing enum201907L(C++20)P1099R5
__cpp_variable_templates变量模板201304L(C++14)N3651
__cpp_variadic_friend变参友元声明202403L(C++26)P2893R3
__cpp_variadic_templates变参模板200704L(C++11)N2242
__cpp_variadic_usingusing 声明中的包展开201611L(C++17)P0195R2
宏的总数量:76

标准库功能特性

下列宏可以用来检测当前实现是否实现了某个标准库功能特性。和语言功能特性测试宏不同,它们不会被预定义,而是由标头 <version> 提供。

对于每个标准库功能特性宏,它也会由提供了与该宏相关的标准库组件的标头提供。完整表单列表请参阅库功能特性测试宏

每个宏都展开成它对应的功能特性被包含于工作草案时的年份与月份的相应整数字面量。当功能特性发生了显著变更时,宏会相应地更新。

宏名功能特性标准标准文件
__cpp_lib_adaptor_iterator_pair_constructorstd::stackstd::queue 的迭代器对构造函数202106L(C++23)P1425R4
__cpp_lib_addressof_constexprconstexpr 的 std::addressof201603L(C++17)LWG2296
__cpp_lib_algorithm_default_value_type为各算法启用列表初始化202403L(C++26)P2248R8
P3217R0
__cpp_lib_algorithm_iterator_requirements范围迭代器作为非范围算法的输入202207L(C++23)P2408R5
__cpp_lib_aligned_accessorstd::aligned_accessor:采用过量对齐指针的 std::mdspan 访问器202411L(C++26)P2897R7
__cpp_lib_allocate_at_least反馈大小的分配器接口,例如:std::allocator::allocate_at_leaststd::allocator_traits::allocate_at_least202302L(C++23)P0401R6
P2652R2
LWG3887
__cpp_lib_allocator_traits_is_always_equalstd::allocator_traits::is_always_equal,清理 noexcept201411L(C++17)N4258
__cpp_lib_anystd::any201606L(C++17)P0220R1
P0032R3
__cpp_lib_applystd::apply201603L(C++17)P0220R1
__cpp_lib_array_constexprconstexpr 的 std::reverse_iteratorstd::move_iteratorstd::array范围访问201603L(C++17)P0031R0
常量表达式迭代器 (ConstexprIterator) std::arrayconstexpr 比较;其他的 constexprstd::array::fill 等)201811L(C++20)P0858R0
LWG3257
P1023R0
P1032R1
__cpp_lib_as_conststd::as_const201510L(C++17)P0007R1
__cpp_lib_associative_heterogeneous_erasure关联容器无序关联容器的异质擦除202110L(C++23)P2077R3
__cpp_lib_associative_heterogeneous_insertion剩余的有序无序关联容器中剩余成员函数的异质重载202306L(C++26)P2363R5
__cpp_lib_assume_alignedstd::assume_aligned201811L(C++20)P1007R3
__cpp_lib_atomic_flag_teststd::atomic_flag::test201907L(C++20)P1135R6
__cpp_lib_atomic_float原子浮点类型201711L(C++20)P0020R6
__cpp_lib_atomic_is_always_lock_freeconstexpr 的 std::atomic<T>::is_always_lock_free201603L(C++17)P0152R1
__cpp_lib_atomic_lock_free_type_aliases原子免锁整数类型(std::atomic_signed_lock_freestd::atomic_unsigned_lock_free201907L(C++20)P1135R6
__cpp_lib_atomic_min_max原子最大值和最小值(std::atomic::fetch_minstd::atomic::fetch_max 等)202403L(C++26)P0493R5
__cpp_lib_atomic_refstd::atomic_ref201806L(C++20)P0019R8
std::atomic_ref::address()202411L(C++26)P2835R7
__cpp_lib_atomic_shared_ptrstd::atomic<std::shared_ptr>201711L(C++20)P0718R2
__cpp_lib_atomic_value_initialization修复原子初始化(默认进行 std::atomic 值初始化)201911L(C++20)P0883R2
__cpp_lib_atomic_wait高效的 std::atomic 等待201907L(C++20)P1135R6
__cpp_lib_barrierstd::barrier201907L(C++20)P1135R6
std::barrier 的阶段完成保障202302L(C++23)P2588R3
__cpp_lib_bind_backstd::bind_back202202L(C++23)P2387R3
允许将可调用对象作为非类型模板实参传递给 std::bind_back202306L(C++26)P2714R1
__cpp_lib_bind_frontstd::bind_front201907L(C++20)P0356R5
P1651R0
允许将可调用对象作为非类型模板实参传递给 std::bind_front202306L(C++26)P2714R1
__cpp_lib_bit_caststd::bit_cast201806L(C++20)P0476R2
__cpp_lib_bitops位操纵201907L(C++20)P0553R4
__cpp_lib_bitsetstd::bitsetstd::string_view 接口202306L(C++26)P2697R1
__cpp_lib_bool_constantstd::bool_constant201505L(C++17)N4389
__cpp_lib_bounded_array_traitsstd::is_bounded_arraystd::is_unbounded_array201902L(C++20)P1357R1
__cpp_lib_boyer_moore_searcher搜索器201603L(C++17)P0220R1
__cpp_lib_bytestd::byte201603L(C++17)P0298R3
__cpp_lib_byteswapstd::byteswap202110L(C++23)P1272R4
__cpp_lib_char8_tchar8_t 的库支持201907L(C++20)P0482R6
P1423R3
__cpp_lib_chronostd::chrono::durationstd::chrono::time_point 的舍入函数201510L(C++17)P0092R1
使得 std::chrono::durationstd::chrono::time_point 的所有成员函数 constexpr201611LP0505R0
日历时区201907L(C++20)P0355R7
P1466R3
std::chrono 值类的散列支持202306L(C++26)P2592R3
__cpp_lib_chrono_udls时间类型的用户定义字面量201304L(C++14)N3642
__cpp_lib_clampstd::clamp201603L(C++17)P0025R1
__cpp_lib_common_reference使 std::reference_wrapperstd::common_reference_t 是引用类型202302L(C++23)P2655R3
__cpp_lib_common_reference_wrapper使 std::reference_wrapperstd::common_reference_t 是引用类型202302L(C++23)P2655R3
__cpp_lib_complex_udlsstd::complex 的用户定义字面量]]201309L(C++14)N3779
__cpp_lib_concepts标准库概念202002L(C++20)P0898R3
P1754R1
P1964R2
仅移动类型的 equality_comparable_withtotally_ordered_withthree_way_comparable_with202207L(C++23)P2404R3
__cpp_lib_constexpr_algorithmsconstexpr 的算法201806L(C++20)P0202R3
P0879R0
LWG3256
LWG3792
constexpr 的稳定排序202306L(C++26)P2562R1
__cpp_lib_constexpr_atomicconstexpr std::atomicstd::atomic_ref202411L(C++26)P3309R3
__cpp_lib_constexpr_bitset使 std::bitsetconstexpr202207L(C++23)P2417R2
__cpp_lib_constexpr_charconvconstexpr 的 std::to_charsstd::from_chars 对整数类型的重载202207L(C++23)P2291R3
__cpp_lib_constexpr_cmathconstexpr 的 <cmath><cstdlib> 中的数学函数202202L(C++23)P0533R9
使 <cmath>constexpr202306L(C++26)P1383R2
__cpp_lib_constexpr_complexconstexpr 的 std::complex201711L(C++20)P0415R1
使 <complex>constexpr202306L(C++26)P1383R2
__cpp_lib_constexpr_containersconstexpr 的容器和适配器202502L(C++26)P3372R2
__cpp_lib_constexpr_dynamic_allocconstexpr 的 std::allocator 和相关工具201907L(C++20)P0784R7
__cpp_lib_constexpr_exceptions异常类型的 constexpr,例如 std::bad_allocstd::bad_cast202411L(C++26)P3068R6
使异常类型更 constexpr202502LP3378R2
__cpp_lib_constexpr_functional其他部分的 constexprstd::default_searcher);constexprINVOKE201907L(C++20)P1032R1
P1065R2
__cpp_lib_constexpr_inplace_vector非平凡类型 std::inplace_vectorconstexpr202502L(C++26)P3074R7
__cpp_lib_constexpr_iterator其他部分的 constexprstd::insert_iterator 等)201811L(C++20)P1032R1
__cpp_lib_constexpr_memoryconstexpr 的 std::pointer_traits201811L(C++20)P1006R1
constexpr 的 std::unique_ptr202202L(C++23)P2273R3
__cpp_lib_constexpr_newconstexpr 的 布置 new202406L(C++26)P2747R2
__cpp_lib_constexpr_numeric<numeric> 中的 constexpr 的 算法201911L(C++20)P1645R1
__cpp_lib_constexpr_stringconstexpr std::char_traits201611L(C++17)P0426R1
constexpr std::string201907L(C++20)P0980R1
__cpp_lib_constexpr_string_view其他部分的 constexprstd::string_view::copy201811L(C++20)P1032R1
__cpp_lib_constexpr_tuple其他部分的 constexprstd::tuple::operator= 等)201811L(C++20)P1032R1
__cpp_lib_constexpr_typeinfoconstexpr 的 std::type_info::operator==202106L(C++23)P1328R1
__cpp_lib_constexpr_utility其他部分的 constexprstd::pair::operator= 等)201811L(C++20)P1032R1
__cpp_lib_constexpr_vectorconstexpr 的 std::vector201907L(C++20)P1004R2
__cpp_lib_constrained_equalitystd::pairstd::tuplestd::optionalstd::variant 的受约束关系运算符202403L(C++26)P2944R3
约束 std::expected相等性运算符202411LP3379R0
__cpp_lib_containers_ranges字符串和容器的范围构造和插入202202L(C++23)P1206R7
__cpp_lib_contracts<contracts>:契约支持202502L(C++26)P2900R14
__cpp_lib_copyable_functionstd::copyable_function202306L(C++26)P2548R6
__cpp_lib_coroutine协程(库支持)201902L(C++20)P0912R5
LWG3393
__cpp_lib_debugging<debugging>调试支持202311L(C++26)P2546R5
可替换 std::is_debugger_present202403LP2810R4
__cpp_lib_destroying_delete销毁的 operator delete(库支持)201806L(C++20)P0722R3
__cpp_lib_enable_shared_from_thisstd::enable_shared_from_this::weak_from_this201603L(C++17)P0033R1
__cpp_lib_endianstd::endian201907L(C++20)P0463R1
P1612R1
__cpp_lib_erase_if统一的容器擦除202002L(C++20)P1209R0
P1115R3
__cpp_lib_exchange_functionstd::exchange201304L(C++14)N3668
__cpp_lib_execution执行策略201603L(C++17)P0024R2
std::execution::unsequenced_policy201902L(C++20)P1001R2
__cpp_lib_expected类模板 std::expected202202L(C++23)P0323R12
std::expected 的单子式函数202211LP2505R5
__cpp_lib_filesystem文件系统库201703L(C++17)P0218R1
P0219R1
P0392R0
P0317R1
__cpp_lib_flat_mapstd::flat_mapstd::flat_multimap202207L(C++23)P0429R9
__cpp_lib_flat_setstd::flat_setstd::flat_multiset202207L(C++23)P1222R4
LWG3751
__cpp_lib_format文本格式化201907L(C++20)P0645R10
P1361R2
P1652R1
编译时格式字符串检查;减少 std::vformat_to 的参数化202106L(C++23)
(DR20)
P2216R3
修复 chrono 格式化器中的本地环境处理;支持非 const 可格式化类型202110LP2372R3
P2418R2
暴露 std::basic_format_string;澄清 chrono 类型的本地化的格式化的编码处理202207L(C++23)P2419R2
P2508R1
格式化指针202304L(C++26)P2510R3
格式化参数的类型检查202305LP2757R3
visit 成员202306LP2637R3
运行时格式字符串202311LP2918R2
__cpp_lib_format_pathstd::filesystem::path 的格式化202403L(C++26)P2845R8
__cpp_lib_format_ranges格式化范围202207L(C++23)P2286R8
P2585R1
LWG3750
__cpp_lib_format_uchar修正代码单元作为整数的格式化202311L(C++26)P2909R4
__cpp_lib_formatters格式化 std::thread::idstd::stacktrace202302L(C++23)P2693R1
__cpp_lib_forward_likestd::forward_like202207L(C++23)P2445R1
__cpp_lib_freestanding_algorithm<algorithm> 中的独立设施202311L(C++26)P2407R5
__cpp_lib_freestanding_array使 std::array 的部分功能独立202311L(C++26)P2407R5
__cpp_lib_freestanding_char_traits独立的 std::char_traits202306L(C++26)P2338R4
__cpp_lib_freestanding_charconv<charconv> 中的独立设施202306L(C++26)P2338R4
__cpp_lib_freestanding_cstdlib<cstdlib> 中的独立设施202306L(C++26)P2338R4
__cpp_lib_freestanding_cstring<cstring> 中的独立设施202306L(C++26)P2338R4
从独立设施中移除 std::strtok202311LP2937R0
__cpp_lib_freestanding_cwchar<cwchar> 中的独立设施202306L(C++26)P2338R4
__cpp_lib_freestanding_errc独立的 std::errc202306L(C++26)P2338R4
__cpp_lib_freestanding_expected使 std::expected 的部分功能独立202311L(C++26)P2833R2
__cpp_lib_freestanding_feature_test_macros支持独立的功能特性测试宏202306L(C++26)P2198R7
__cpp_lib_freestanding_functional<functional> 中的独立设施202306L(C++26)P2198R7
__cpp_lib_freestanding_iterator<iterator> 中的独立设施202306L(C++26)P2198R7
__cpp_lib_freestanding_mdspan独立的 std::mdspan202311L(C++26)P2833R2
__cpp_lib_freestanding_memory<memory> 中的独立设施202306L(C++26)P2198R7
__cpp_lib_freestanding_numeric<numeric> 中的独立设施(饱和算术)202311L(C++26)P0543R3
__cpp_lib_freestanding_operator_newoperator new 的定义(在独立实现中可选)202306L(C++26)P2198R7
__cpp_lib_freestanding_optional使 std::optional 的部分功能独立202311L(C++26)P2407R5
__cpp_lib_freestanding_ranges<ranges> 中的独立设施202306L(C++26)P2198R7
__cpp_lib_freestanding_ratio<ratio> 中的独立设施202306L(C++26)P2198R7
__cpp_lib_freestanding_string_view使 std::string_view 的部分功能独立202311L(C++26)P2407R5
__cpp_lib_freestanding_tuple<tuple> 中的独立设施202306L(C++26)P2198R7
__cpp_lib_freestanding_utility<utility> 中的独立设施202306L(C++26)P2198R7
__cpp_lib_freestanding_variant使 std::variant 的部分功能独立202311L(C++26)P2407R5
__cpp_lib_fstream_native_handle获得文件流的原生把柄202306L(C++26)P1759R6
__cpp_lib_function_refstd::function_ref:类型擦除的可调用对象的引用202306L(C++26)P0792R14
__cpp_lib_gcd_lcmstd::gcdstd::lcm201606L(C++17)P0295R0
__cpp_lib_generatorstd::generator:范围的同步协程生成器202207L(C++23)P2502R2
__cpp_lib_generic_associative_lookup关联容器的异质比较查找201304L(C++14)N3657
__cpp_lib_generic_unordered_lookup无序关联容器的异质比较查找201811L(C++20)P0919R3
__cpp_lib_hardware_interference_sizeconstexpr 的 std::hardware_{constructive, destructive}_interference_size201703L(C++17)P0154R1
__cpp_lib_hive<hive>:一种基于桶的容器,可重用已擦除元素的内存位置202502L(C++26)P0447R28
__cpp_lib_has_unique_object_representationsstd::has_unique_object_representations201606L(C++17)P0258R2
__cpp_lib_hazard_pointer<hazard_pointer>:风险指针202306L(C++26)P2530R3
__cpp_lib_hypotstd::hypot 的三实参重载201603L(C++17)P0030R1
__cpp_lib_incomplete_container_elementsstd::forward_liststd::liststd::vector 的最小化不完整类型支持201505L(C++17)N4510
__cpp_lib_indirectstd::indirect202502L(C++26)P3019R13
__cpp_lib_inplace_vectorstd::inplace_vector:可动态调整大小的固定容量向量(原位存储)202406L(C++26)P0843R14
__cpp_lib_int_pow22 的整数次幂运算std::has_single_bitstd::bit_ceilstd::bit_floorstd::bit_width202002L(C++20)P0556R3
P1956R1
__cpp_lib_integer_comparison_functions整数比较函数202002L(C++20)P0586R2
__cpp_lib_integer_sequence编译期的整数序列201304L(C++14)N3658
__cpp_lib_integral_constant_callablestd::integral_constant::operator()201304L(C++14)N3545
__cpp_lib_interpolatestd::lerpstd::midpoint201902L(C++20)P0811R3
__cpp_lib_invokestd::invoke201411L(C++17)N4169
__cpp_lib_invoke_rstd::invoke_r202106L(C++23)P2136R3
__cpp_lib_ios_noreplace为 fstream 添加排他模式202207L(C++23)P2467R1
__cpp_lib_is_aggregatestd::is_aggregate201703L(C++17)LWG2911
__cpp_lib_is_constant_evaluatedstd::is_constant_evaluated201811L(C++20)P0595R2
__cpp_lib_is_finalstd::is_final201402L(C++14)LWG2112
__cpp_lib_is_implicit_lifetimestd::is_implicit_lifetime202302L(C++23)P2674R1
__cpp_lib_is_invocablestd::is_invocablestd::invoke_result201703L(C++17)P0604R0
__cpp_lib_is_layout_compatiblestd::is_layout_compatible201907L(C++20)P0466R5
__cpp_lib_is_nothrow_convertiblestd::is_convertible201806L(C++20)P0758R1
LWG3356
__cpp_lib_is_null_pointerstd::is_null_pointer201309L(C++14)
(DR11)
LWG2247
__cpp_lib_is_pointer_interconvertible指针可互转换特征:std::is_pointer_interconvertible_with_classstd::is_pointer_interconvertible_base_of201907L(C++20)P0466R5
__cpp_lib_is_scoped_enumstd::is_scoped_enum202011L(C++23)P1048R1
__cpp_lib_is_sufficiently_alignedstd::is_sufficiently_aligned:检查指针对齐前条件202411L(C++26)P2897R7
__cpp_lib_is_swappable(不抛出的)可交换特征201603L(C++17)P0185R1
__cpp_lib_is_virtual_base_ofstd::is_virtual_base_of:用于检测虚基类的类型特征202406L(C++26)P2985R0
__cpp_lib_is_within_lifetime检查联合体可选项是否活跃(std::is_within_lifetime202306L(C++26)P2641R4
__cpp_lib_jthread停止令牌自动合并线程201911L(C++20)P0660R10
P1869R1
__cpp_lib_latchstd::latch201907L(C++20)P1135R6
__cpp_lib_launderCWG 问题 1776:替换包含引用成员的类对象(std::launder201606L(C++17)P0137R1
__cpp_lib_linalg一套基于 BLAS 的自由函数线性代数接口202311L(C++26)P1673R13
__cpp_lib_list_remove_return_type修改 std::forward_liststd::listremove()remove_if()unique() 成员的返回值类型201806L(C++20)P0646R1
__cpp_lib_logical_traits类型特征的逻辑运算201510L(C++17)P0013R1
__cpp_lib_make_from_tuplestd::make_from_tuple201606L(C++17)P0209R2
__cpp_lib_make_reverse_iteratorstd::make_reverse_iterator201402L(C++14)LWG2285
__cpp_lib_make_uniquestd::make_unique201304L(C++14)N3656
__cpp_lib_map_try_emplacestd::map::try_emplacestd::map::insert_or_assign201411L(C++17)N4279
__cpp_lib_math_constants数学常量201907L(C++20)P0631R8
__cpp_lib_math_special_functions特殊数学函数201603L(C++17)P0226R1
__cpp_lib_mdspanstd::mdspan202207L(C++23)P0009R18
P2599R2
P2604R0
P2613R1
std::mdspanstd::dims202406L(C++26)P2389R2
__cpp_lib_memory_resourcestd::pmr::memory_resource201603L(C++17)P0220R1
__cpp_lib_modules标准库模块 stdstd.compat202207L(C++23)P2465R3
__cpp_lib_move_iterator_concept使 std::move_iterator<T*> 是随机访问迭代器202207L(C++23)P2520R0
__cpp_lib_move_only_functionstd::move_only_function202110L(C++23)P0288R9
__cpp_lib_node_extract拼合映射和集合(std::map::extractstd::map::mergestd::map::insert(node_type) 等)201606L(C++17)P0083R3
__cpp_lib_nonmember_container_accessstd::sizestd::datastd::empty201411L(C++17)N4280
__cpp_lib_not_fnstd::not_fn201603L(C++17)P0005R4
允许将可调用对象作为非类型模板实参传递给 std::not_fn202306L(C++26)P2714R1
__cpp_lib_null_iterators空的老式向前迭代器 (LegacyForwardIterator) 201304L(C++14)N3644
__cpp_lib_optionalstd::optional201606L(C++17)P0220R1
P0032R3
P0307R2
完全 constexprstd::optional202106L(C++23)
(DR20)
P2231R1
std::optional单子式运算202110L(C++23)P0798R8
LWG3621
__cpp_lib_optional_range_supportstd::optional 的范围支持202406L(C++26)P3168R2
__cpp_lib_out_ptrstd::out_ptrstd::inout_ptr202106L(C++23)P1132R8
独立的 std::out_ptrstd::inout_ptr202311L(C++26)P2833R2
__cpp_lib_parallel_algorithm并行算法201603L(C++17)P0024R2
__cpp_lib_polymorphicstd::polymorphic202502L(C++26)P3019R13
__cpp_lib_polymorphic_allocatorstd::pmr::polymorphic_allocator<> 作为基础词汇类型201902L(C++20)P0339R6
LWG3437
__cpp_lib_print格式化的输出202207L(C++23)P2093R14
允许一种 std::print 高效实现202403L(C++26)
(DR23)
P3107R5
P3235R3
std::println 打印空行202403L(C++26)P3142R0
__cpp_lib_quoted_string_iostd::quoted201304L(C++14)N3654
__cpp_lib_philox_enginestd::philox_engine:基于计数器的随机数引擎202406L(C++26)P2075R6
__cpp_lib_ranges范围库受约束算法201911L(C++20)P0896R4
P1035R7
P1716R3
可默认初始化视图202106L(C++23)
(DR20)
P2325R3
所有权视图202110LP2415R2
std::ranges::range_adaptor_closure202202L(C++23)P2387R3
放松对范围适配器要求以允许仅移动类型202207LP2494R2
移除 ranges::beginranges::endranges::rbeginranges::rendranges::size 的“毒药丸”重载202211LP2602R2
放松对范围要求以允许某些投影202302LP2609R3
移除可间接调用概念中的公共引用要求202406L(C++26)
(DR20)
P2997R1
__cpp_lib_ranges_as_conststd::const_iteratorstd::ranges::as_const_view202207L(C++23)P2278R4
使 std::basic_const_iterator 遵守其底层类型的可转换性202311L(C++26)P2836R1
__cpp_lib_ranges_as_rvaluestd::ranges::as_rvalue_view202207L(C++23)P2446R2
__cpp_lib_ranges_cache_lateststd::ranges::cache_latest_view202411L(C++26)P3138R5
__cpp_lib_ranges_cartesian_productstd::ranges::cartesian_product_view202207L(C++23)P2374R4
P2540R1
__cpp_lib_ranges_chunkstd::ranges::chunk_view202202L(C++23)P2442R1
__cpp_lib_ranges_chunk_bystd::ranges::chunk_by_view202202L(C++23)P2443R1
__cpp_lib_ranges_concatstd::ranges::concat_view202403L(C++26)P2542R8
__cpp_lib_ranges_containsstd::ranges::contains202207L(C++23)P2302R4
__cpp_lib_ranges_enumeratestd::ranges::enumerate_view202302L(C++23)P2164R9
__cpp_lib_ranges_find_laststd::ranges::find_laststd::ranges::find_last_ifstd::ranges::find_last_if_not202207L(C++23)P1223R5
LWG3807
__cpp_lib_ranges_foldstd::ranges 折叠算法202207L(C++23)P2322R6
__cpp_lib_ranges_generate_random随机数生成的向量 API(std::ranges::generate_random202403L(C++26)P1068R11
__cpp_lib_ranges_iotastd::ranges::iota202202L(C++23)P2440R1
__cpp_lib_ranges_join_withstd::ranges::join_with_view202202L(C++23)P2441R2
__cpp_lib_ranges_repeatstd::ranges::repeat_view202207L(C++23)P2474R2
__cpp_lib_ranges_reserve_hintstd::ranges::approximately_sized_rangestd::ranges::reserve_hint202502L(C++26)P2846R6
__cpp_lib_ranges_slidestd::ranges::slide_view202202L(C++23)P2442R1
__cpp_lib_ranges_starts_ends_withstd::ranges::starts_withstd::ranges::ends_with202106L(C++23)P1659R3
__cpp_lib_ranges_stridestd::ranges::stride_view202207L(C++23)P1899R3
__cpp_lib_ranges_to_containerstd::ranges::to202202L(C++23)P1206R7
__cpp_lib_ranges_to_inputstd::ranges::to_input_view202502L(C++26)P3137R3
__cpp_lib_ranges_zipstd::ranges::zip_view, std::ranges::zip_transform_view, std::ranges::adjacent_viewstd::ranges::adjacent_transform_view202110L(C++23)P2321R2
__cpp_lib_ratio添加新的 2022 国际单位制(SI)前缀202306L(C++26)P2734R0
__cpp_lib_raw_memory_algorithms扩展的内存管理工具201606L(C++17)P0040R3
constexpr特化内存算法202411L(C++26)P3508R0
P3369R0
__cpp_lib_rcu<rcu>:读-复制更新(RCU)202306L(C++26)P2545R4
__cpp_lib_reference_from_temporarystd::reference_constructs_from_temporarystd::reference_converts_from_temporary202202L(C++23)P2255R2
__cpp_lib_reference_wrapperstd::reference_wrapper 的比较202403L(C++26)P2944R3
__cpp_lib_remove_cvrefstd::remove_cvref201711L(C++20)P0550R2
__cpp_lib_result_of_sfinaestd::result_ofSFINAE201210L(C++14)N3462
__cpp_lib_robust_nonmodifying_seq_ops使非修改的序列操作更加稳健(std::mismatchstd::equalstd::is_permutation 的两范围重载)201304L(C++14)N3671
__cpp_lib_samplestd::sample201603L(C++17)P0220R1
__cpp_lib_saturation_arithmetic饱和算术202311L(C++26)P0543R3
__cpp_lib_scoped_lockstd::scoped_lock201703L(C++17)P0156R2
__cpp_lib_semaphorestd::counting_semaphorestd::binary_semaphore201907L(C++20)P1135R6
__cpp_lib_sendersstd::execution:执行控制的发送器/接收器模型202406L(C++26)P2300R10
__cpp_lib_shared_mutexstd::shared_mutex(无时限)201505L(C++17)N4508
__cpp_lib_shared_ptr_arraysstd::shared_ptr<T[]>201611L(C++17)P0497R0
std::make_shared 的数组支持201707L(C++20)P0674R1
__cpp_lib_shared_ptr_weak_typeshared_ptr::weak_type201606L(C++17)P0163R0
__cpp_lib_shared_timed_mutexstd::shared_timed_mutex201402L(C++14)N3891
__cpp_lib_shiftstd::shift_leftstd::shift_right201806L(C++20)P0769R2
std::ranges::shift_leftstd::ranges::shift_right202202L(C++23)P2440R1
__cpp_lib_simd<simd>: 数据并行类型202411L(C++26)P1928R15
__cpp_lib_smart_ptr_for_overwrite用默认初始化创建智能指针(std::allocate_shared_for_overwritestd::make_shared_for_overwritestd::make_unique_for_overwrite202002L(C++20)P1020R1
P1973R1
__cpp_lib_smart_ptr_owner_equality使得 std::weak_ptr 可以作为无序关联容器的键202306L(C++26)P1901R2
__cpp_lib_source_location源代码信息捕获(std::source_location201907L(C++20)P1208R6
__cpp_lib_spanstd::span202002L(C++20)P0122R7
LWG3274
P1024R3
P1976R2
使 std::span 的部分功能独立202311L(C++26)P2821R5
P2833R2
__cpp_lib_span_initializer_list从初始化器列表构造 std::span202311L(C++26)P2447R6
__cpp_lib_spanstreamstd::spanbufstd::spanstream202106L(C++23)P0448R4
__cpp_lib_ssizestd::ssize 和无符号 std::span::size201902L(C++20)P1227R2
__cpp_lib_sstream_from_string_viewstd::stringstreamstd::string_view 接口202306L(C++26)P2495R3
__cpp_lib_stacktrace栈踪迹库202011L(C++23)P0881R7
__cpp_lib_start_lifetime_as显式生存期管理(std::start_lifetime_as202207L(C++23)P2590R2
__cpp_lib_starts_ends_with字符串前缀和后缀检查(用于 std::stringstd::string_viewstarts_with()ends_with()201711L(C++20)P0457R2
__cpp_lib_stdatomic_h用于 C 原子操作的兼容头文件202011L(C++23)P0943R6
__cpp_lib_string_containsstd::basic_stringstd::basic_string_viewcontains 函数202011L(C++23)P1679R3
__cpp_lib_string_resize_and_overwritestd::basic_string::resize_and_overwrite202110L(C++23)P1072R10
__cpp_lib_string_udls字符串类型的用户定义字面量201304L(C++14)N3642
__cpp_lib_string_viewstd::string_view201606L(C++17)P0220R1
P0254R2
常量表达式迭代器 (ConstexprIterator) 201803L(C++20)P0858R0
LWG3257
拼接 std::stringstd::string_view202403L(C++26)P2591R5
__cpp_lib_submdspanstd::submdspan202306L(C++26)P2630R4
有填充 mdspan 布局202403LP2642R6
__cpp_lib_syncbuf同步的带缓冲输出流(std::syncbufstd::osyncstream)和操纵符201803L(C++20)P0053R7
P0753R2
__cpp_lib_text_encodingstd::text_encoding202306L(C++26)P1885R12
__cpp_lib_three_way_comparison三路比较(库支持):向库添加三路比较201907L(C++20)P0768R1
P1614R2
__cpp_lib_to_address将指针转换为原生指针的工具(std::to_address201711L(C++20)P0653R2
__cpp_lib_to_arraystd::to_array201907L(C++20)P0325R4
__cpp_lib_to_chars初等字符串转换 (std::to_charsstd::from_chars201611L(C++17)P0067R5
P0682R1
LWG3137
测试 <charconv> 函数的成功或失败202306L(C++26)P2497R0
__cpp_lib_to_string使用 std::format 重定义 std::to_string202306L(C++26)P2587R3
__cpp_lib_to_underlyingstd::to_underlying202102L(C++23)P1682R3
__cpp_lib_transformation_trait_aliases变换特征的别名模板201304L(C++14)N3655
__cpp_lib_transparent_operators透明的运算符函数对象(std::less<> 等)201210L(C++14)N3421
透明的 std::owner_lessstd::owner_less<void>201510L(C++17)P0074R0
__cpp_lib_trivially_relocatable可平凡重定位性的特征与操作202502L(C++26)N2786R13
__cpp_lib_tuple_element_tstd::tuple_element_t201402L(C++14)N3887
__cpp_lib_tuple_likestd::tuple 和元组式对象(std::pairstd::arraystd::subrange)间的兼容性202207L(C++23)P2165R4
std::complex 添加元组协议202311L(C++26)P2819R2
__cpp_lib_tuples_by_type根据类型寻址元组201304L(C++14)N3670
__cpp_lib_type_identitystd::type_identity201806L(C++20)P0887R1
__cpp_lib_type_trait_variable_templates类型特征变量模板(std::is_void_v 等)201510L(C++17)P0006R0
__cpp_lib_uncaught_exceptionsstd::uncaught_exceptions201411L(C++17)N4259
__cpp_lib_unordered_map_try_emplacestd::unordered_map::try_emplacestd::unordered_map::insert_or_assign201411L(C++17)N4279
__cpp_lib_unreachablestd::unreachable202202L(C++23)P0627R6
__cpp_lib_unwrap_refstd::unwrap_ref_decaystd::unwrap_reference201811L(C++20)P0318R1
LWG3348
__cpp_lib_variantstd::variant:C++17 的类型安全的联合体201606L(C++17)P0088R3
P0393R3
P0032R3
用于 std::variant 派生类的 std::visit202102L(C++23)
(DR17)
P2162R2
完全 constexprstd::variant202106L(C++23)
(DR20)
P2231R1
visit 成员202306L(C++26)P2637R3
__cpp_lib_void_tstd::void_t201411L(C++17)N3911
宏的总数量:255

示例

正常使用

#ifdef __has_include                           // 检查 __has_include 是否存在
#  if __has_include(<optional>)                // 检查标准库
#    include <optional>
#  elif __has_include(<experimental/optional>) // 检查实验版本
#    include <experimental/optional>
#  elif __has_include(<boost/optional.hpp>)    // 尝试外部库
#    include <boost/optional.hpp>
#  else                                        // 完全找不到
#     error "Missing <optional>"
#  endif
#endif
 
#ifdef __has_cpp_attribute                      // 检查 __has_cpp_attribute 是否存在
#  if __has_cpp_attribute(deprecated)           // 检查一个属性
#    define DEPRECATED(msg) [[deprecated(msg)]]
#  endif
#endif
#ifndef DEPRECATED
#    define DEPRECATED(msg)
#endif
 
DEPRECATED("foo() has been deprecated") void foo();
 
#if __cpp_constexpr >= 201304                   // 检查功能特性的指定版本
#  define CONSTEXPR constexpr
#else
#  define CONSTEXPR inline
#endif
 
CONSTEXPR int bar(unsigned i)
{
#ifdef __cpp_binary_literals                    // 检查功能特性是否存在
    unsigned mask1 = 0b11000000;
    unsigned mask2 = 0b00000111;
#else
    unsigned mask1 = 0xA0;
    unsigned mask2 = 0x07;
#endif
    if (i & mask1)
        return 1;
    if (i & mask2)
        return 2;
    return 0;
}
 
int main() {}

编译器功能特性输出

以下(兼容 C++11)程序将转储 C++ 编译器的功能和属性。 注意 __has_cpp_attribute() 的使用并不遵从标准而是依赖于 gcc/clang 实现。

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

可能的输出:

C++11 CORE (20/20)
__cpp_alias_templates                         2007-04  =  2007-04
__cpp_attributes                              2008-09  =  2008-09
__cpp_constexpr                               2022-11  >  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                               2022-11  >  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 ...
 
... truncated ...
 
C++23 LIB (43/64)
__cpp_lib_adaptor_iterator_pair_constructor   2021-06  =  2021-06
__cpp_lib_algorithm_iterator_requirements     -------  <  2022-07
__cpp_lib_allocate_at_least                   -------  <  2023-02
__cpp_lib_associative_heterogeneous_erasure   -------  <  2021-10
__cpp_lib_barrier                             2019-07  <  2023-02
... truncated ...
 
ALL CORE MACROS UP TO C++26 (60/76)
__cpp_aggregate_bases                         2016-03  =  2016-03
__cpp_aggregate_nsdmi                         2013-04  =  2013-04
__cpp_aggregate_paren_init                    2019-02  =  2019-02
__cpp_alias_templates                         2007-04  =  2007-04
... truncated ...
 
ALL LIB MACROS UP TO C++26 (158/255)
__cpp_lib_adaptor_iterator_pair_constructor   2021-06  =  2021-06
__cpp_lib_addressof_constexpr                 2016-03  =  2016-03
__cpp_lib_algorithm_iterator_requirements     -------  <  2022-07
__cpp_lib_allocate_at_least                   -------  <  2023-02
__cpp_lib_allocator_traits_is_always_equal    2014-11  =  2014-11
... truncated ...
 
ATTRIBUTES (9/11)
assume                                        2022-07  =  2022-07
carries_dependency                            -------  <  2008-09
deprecated                                    2013-09  =  2013-09
fallthrough                                   2016-03  =  2016-03
... truncated ...
 
Compiler specific macros:
__cplusplus                                   202302L
__GNUG__                                      14
__GNUC_MINOR__                                2
__GNUC_PATCHLEVEL__                           0

缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

缺陷报告应用于出版时的行为正确行为
P2552R3C++20__has_cpp_attribute 对于标准属性必须展开成非零值可以展开成 0

参阅

库功能特性测试宏 (C++20)在标头 <version> 定义
预定义宏符号
宏符号索引

外部链接

1. 特性测试推荐的官方文档
2. 试出编译器特性的源码