功能特性测试 (C++20)
标准中为 C++11 和其后所引入的 C++ 语言和程序库的功能特性定义了一组预处理器宏。标准有意使之成为检测这些功能特性是否存在的一种简单且可移植的方式。
属性
__has_cpp_attribute( 属性记号 )
|
|||||||||
检查(宏展开后) 属性记号 所指名的属性的存在。
对于标准属性,它将展开成该属性被添加到工作草案中时的年份和月份(见下表),特定于厂商的属性则以某个非零值确定。
能在 #if 与 #elif 的表达式中展开 __has_cpp_attribute
。 #ifdef 、 #ifndef 和 defined 把它当做已定义的宏,但不能在别处使用它。
attribute-token | 属性 | 值 | 标准 |
---|---|---|---|
carries_dependency
|
[[carries_dependency]]
|
200809L | (C++11) |
deprecated
|
[[deprecated]]
|
201309L | (C++14) |
fallthrough
|
[[fallthrough]]
|
201603L | (C++17) |
likely
|
[[likely]]
|
201803L | (C++20) |
maybe_unused
|
[[maybe_unused]]
|
201603L | (C++17) |
no_unique_address
|
[[no_unique_address]]
|
201803L | (C++20) |
nodiscard
|
[[nodiscard]]
|
201603L | (C++17) |
noreturn
|
[[noreturn]]
|
200809L | (C++11) |
unlikely
|
[[unlikely]]
|
201803L | (C++20) |
语言功能特性
下列宏预定义于每个翻译单元。每个宏都展开成对应于相应功能特性被包含到工作草案时的年份与月份的整数字面量。
当功能特性发生了显著变更时,宏会相应地更新。
宏名 | 功能特性 | 值 | 标准 |
---|---|---|---|
__cpp_aggregate_bases | 扩展聚合初始化 | 201603L | (C++17) |
__cpp_aggregate_nsdmi | 成员初始化器与聚合体 | 201304L | (C++14) |
__cpp_aggregate_paren_init | 形式为直接初始化的聚合初始化 | 201902L | (C++20) |
__cpp_alias_templates | 别名模版 | 200704L | (C++11) |
__cpp_aligned_new | 过对齐数据的动态内存分配 | 201606L | (C++17) |
__cpp_attributes | 属性 | 200809L | (C++11) |
__cpp_binary_literals | C++ 核心语言中的二进制字面量 | 201304L | (C++14) |
__cpp_capture_star_this | 以 [=,*this] 进行 *this 的按值 lambda 捕获 |
201603L | (C++17) |
__cpp_char8_t | char8_t | 201811L | (C++20) |
__cpp_conditional_explicit | explicit(bool) | 201806L | (C++20) |
__cpp_constexpr | constexpr | 200704L | (C++11) |
放松 constexpr 函数 / constexpr 成员函数上的限制和隐式 const |
201304L | (C++14) | |
Constexpr lambda | 201603L | (C++17) | |
constexpr 函数中的平凡默认初始化与汇编声明 | 201907L | (C++20) | |
__cpp_coroutines | 协程 | 201902L | (C++20) |
__cpp_decltype | decltype | 200707L | (C++11) |
__cpp_decltype_auto | 常规函数的返回类型推导 | 201304L | (C++14) |
__cpp_deduction_guides | 类模板的模板实参推导 | 201703L | (C++17) |
__cpp_delegating_constructors | 委托构造函数 | 200604L | (C++11) |
__cpp_enumerator_attributes | 枚举项的属性 | 201411L | (C++17) |
__cpp_fold_expressions | 折叠表达式 | 201603L | (C++17) |
__cpp_generic_lambdas | 泛型(多态) lambda 表达式 | 201304L | (C++14) |
__cpp_guaranteed_copy_elision | 通过简化值类别保证复制消除 | 201606L | (C++17) |
__cpp_hex_float | 十六进制浮点字面量 | 201603L | (C++17) |
__cpp_if_constexpr | constexpr if | 201606L | (C++17) |
__cpp_impl_destroying_delete | 销毁的 operator delete (编译器支持) |
201806L | (C++20) |
__cpp_impl_three_way_comparison | 三路比较(编译器支持) | 201711L | (C++20) |
__cpp_inheriting_constructors | 继承构造函数 | 200802L | (C++11) |
重述继承构造函数 | 201511L | (C++17) | |
__cpp_init_captures | 通用化的 lambda 捕获 | 201304L | (C++14) |
__cpp_initializer_lists | 初始化器列表 | 200806L | (C++11) |
__cpp_inline_variables | inline 变量 | 201606L | (C++17) |
__cpp_lambdas | Lambda 表达式 | 200907L | (C++11) |
__cpp_namespace_attributes | 命名空间的属性 | 201411L | (C++17) |
__cpp_noexcept_function_type | 令异常规定为类型系统的一部分 | 201510L | (C++17) |
__cpp_nontype_template_args | 允许全部非类型模板实参的常量求值 | 201411L | (C++17) |
__cpp_nontype_template_parameter_auto | 以 auto 声明非类型模板形参 | 201606L | (C++17) |
__cpp_nontype_template_parameter_class | 非类型模板形参中的类类型 | 201806L | (C++20) |
__cpp_nsdmi | 非静态数据成员初始化器 | 200809L | (C++11) |
__cpp_range_based_for | 基于范围的 for 循环 | 200907L | (C++11) |
通用化基于范围的 for 循环 | 201603L | (C++17) | |
__cpp_raw_strings | 原始字符串字面量 | 200710L | (C++11) |
__cpp_ref_qualifiers | 引用限定符 | 200710L | (C++11) |
__cpp_return_type_deduction | 常规函数的返回类型推导 | 201304L | (C++14) |
__cpp_rvalue_references | 右值引用 | 200610L | (C++11) |
__cpp_sized_deallocation | 具大小解分配 | 201309L | (C++14) |
__cpp_static_assert | static_assert | 200410L | (C++11) |
扩展 static_assert |
201411L | (C++17) | |
__cpp_structured_bindings | 结构化绑定 | 201606L | (C++17) |
__cpp_template_template_args | 模板模板实参的匹配 | 201611L | (C++17) |
__cpp_threadsafe_static_init | 带并发的动态初始化和销毁 | 200806L | (C++11) |
__cpp_unicode_characters | 新字符类型( char16_t 与 char32_t ) | 200704L | (C++11) |
__cpp_unicode_literals | Unicode 字符串字面量 | 200710L | (C++11) |
__cpp_user_defined_literals | 用户定义字面量 | 200809L | (C++11) |
__cpp_variable_templates | 变量模板 | 201304L | (C++14) |
__cpp_variadic_templates | 变参模板 | 200704L | (C++11) |
__cpp_variadic_using | using 声明中的包展开 | 201611L | (C++17) |
标准库功能特性
如果包含了头文件 <version> 或下表中的任意对应头文件,则下列各个宏有定义。每个宏都展开成其对应的功能特性被包含于工作草案时的年份与月份的相应整数字面量。
当功能特性发生了显著变更时,宏会相应地更新。
宏名 | 功能特性 | 值 | 头文件 | 标准 |
---|---|---|---|---|
__cpp_lib_addressof_constexpr | constexpr std::addressof | 201603L | <memory> | (C++17) |
__cpp_lib_allocator_traits_is_always_equal | std::allocator_traits::is_always_equal | 201411L | <memory> <scoped_allocator> <string> <deque> <forward_list> <list> <vector> <map> <set> <unordered_map> <unordered_set> | (C++17) |
__cpp_lib_any | std::any | 201606L | <any> | (C++17) |
__cpp_lib_apply | std::apply | 201603L | <tuple> | (C++17) |
__cpp_lib_array_constexpr | 添加 constexpr 修饰符到 std::reverse_iterator 、 std::move_iterator 、 std::array 和容器访问 |
201603L | <iterator> <array> | (C++17) |
__cpp_lib_as_const | std::as_const | 201510L | <utility> | (C++17) |
__cpp_lib_atomic_is_always_lock_free | constexpr atomic<T>::is_always_lock_free | 201603L | <atomic> | (C++17) |
__cpp_lib_atomic_ref | std::atomic_ref | 201806L | <atomic> | (C++20) |
__cpp_lib_bind_front | std::bind_front | 201811L | <functional> | (C++20) |
__cpp_lib_bit_cast | std::bit_cast | 201806L | <bit> | (C++20) |
__cpp_lib_bool_constant | std::bool_constant | 201505L | <type_traits> | (C++17) |
__cpp_lib_bounded_array_traits | std::is_bounded_array, std::is_unbounded_array | 201902L | <type_traits> | (C++20) |
__cpp_lib_boyer_moore_searcher | 搜索器 (Searcher) | 201603L | <functional> | (C++17) |
__cpp_lib_byte | 字节类型的定义 | 201603L | <cstddef> | (C++17) |
__cpp_lib_char8_t | char8_t 的库支持 | 201811L | <atomic> <filesystem> <istream> <limits> <locale> <ostream> <string> <string_view> | (C++20) |
__cpp_lib_chrono | std::chrono::duration 与 std::chrono::time_point 的舍入函数 | 201510L | <chrono> | (C++17) |
令 std::chrono::duration 与 std::chrono::time_point 的所有成员函数为 constexpr | 201611L | <chrono> | (C++17) | |
__cpp_lib_chrono_udls | 时间类型的用户定义字面量 | 201304L | <chrono> | (C++14) |
__cpp_lib_clamp | 在一对边界值间“夹定”值的算法 (std::clamp) | 201603L | <algorithm> | (C++17) |
__cpp_lib_complex_udls | std::complex 的用户定义字面量 |
201309L | <complex> | (C++14) |
__cpp_lib_concepts | 标准库概念 | 201806L | <concepts> | (C++20) |
__cpp_lib_constexpr | 杂项工具设施的 constexpr | 201811L | 任何 C++ 标准库头文件,除了 <*.h>
|
(C++20) |
__cpp_lib_constexpr_swap_algorithms | swap 与交换相关函数的 constexpr | 201806L | <algorithm> | (C++20) |
__cpp_lib_destroying_delete | 销毁的 operator delete (库支持) |
201806L | <new> | (C++20) |
__cpp_lib_enable_shared_from_this | 重述 enable_shared_from_this | 201603L | <memory> | (C++17) |
__cpp_lib_erase_if | 统一容器擦除 | 201811L | <string> <deque> <forward_list> <list> <vector> <map> <set> <unordered_map> <unordered_set> | (C++20) |
__cpp_lib_exchange_function | exchange() 工具函数 |
201304L | <utility> | (C++14) |
__cpp_lib_execution | 执行策略 | 201603L | <execution> | (C++17) |
std::execution::unsequenced_policy | 201902L | <execution> | (C++20) | |
__cpp_lib_filesystem | 文件系统库 | 201703L | <filesystem> | (C++17) |
__cpp_lib_gcd_lcm | std::gcd 、 std::lcm | 201606L | <numeric> | (C++17) |
__cpp_lib_generic_associative_lookup | 为关联容器添加异质查找 | 201304L | <map> <set> | (C++14) |
__cpp_lib_generic_unordered_lookup | 为无序关联容器添加异质查找 | 201811L | <unordered_map> <unordered_set> | (C++20) |
__cpp_lib_hardware_interference_size | constexpr std::hardware_{constructive, destructive}_interference_size |
201703L | <new> | (C++17) |
__cpp_lib_has_unique_object_representations | std::has_unique_object_representations | 201606L | <type_traits> | (C++17) |
__cpp_lib_hypot | std::hypot 的 3 参数重载 | 201603L | <cmath> | (C++17) |
__cpp_lib_incomplete_container_elements | 标准容器对不完整类型的最小支持 | 201505L | <forward_list> <list> <vector> | (C++17) |
__cpp_lib_integer_sequence | 编译时整数数列 | 201304L | <utility> | (C++14) |
__cpp_lib_interpolate | std::lerp(), std::midpoint() | 201902L | <cmath> <numeric> | (C++20) |
__cpp_lib_integral_constant_callable | std::integral_constant::operator() | 201304L | <type_traits> | (C++14) |
__cpp_lib_invoke | std::invoke 函数模板 | 201411L | <functional> | (C++17) |
__cpp_lib_is_aggregate | std::is_aggregate 类型特征 | 201703L | <type_traits> | (C++17) |
__cpp_lib_is_constant_evaluated | 常量求值语境检测 (std::is_constant_evaluated()) | 201811L | <type_traits> | (C++20) |
__cpp_lib_is_final | std::is_final | 201402L | <type_traits> | (C++14) |
__cpp_lib_is_invocable | std::is_invocable 、 std::invoke_result | 201703L | <type_traits> | (C++17) |
__cpp_lib_is_null_pointer | std::is_null_pointer | 201309L | <type_traits> | (C++14) |
__cpp_lib_is_swappable | [nothrow-]swappable 特征 | 201603L | <type_traits> | (C++17) |
__cpp_lib_launder | 核心问题 1776 :替换含引用成员的类对象 (std::launder) | 201606L | <new> | (C++17) |
__cpp_lib_list_remove_return_type | 更改 std::forward_list 与 std::list 的 remove() 、 remove_if() 及 unique() 成员的返回类型 | 201806L | <forward_list> <list> | (C++20) |
__cpp_lib_logical_traits | 逻辑运算符类型特征 | 201510L | <type_traits> | (C++17) |
__cpp_lib_make_from_tuple | std::make_from_tuple :用于构造的 apply | 201606L | <tuple> | (C++17) |
__cpp_lib_make_reverse_iterator | std::make_reverse_iterator | 201402L | <iterator> | (C++14) |
__cpp_lib_make_unique | std::make_unique | 201304L | <memory> | (C++14) |
__cpp_lib_map_try_emplace | std::map::try_emplace, std::map::insert_or_assign | 201411L | <map> | (C++17) |
__cpp_lib_math_special_functions | C++17 的数学特殊函数 | 201603L | <cmath> | (C++17) |
__cpp_lib_memory_resource | std::pmr::memory_resource | 201603L | <memory_resource> | (C++17) |
__cpp_lib_node_extract | 拼拆 map 和 set ( std::map::extract 、 std::map::merge 、 std::map::insert(node_type) 等) |
201606L | <map> <set> <unordered_map> <unordered_set> | (C++17) |
__cpp_lib_nonmember_container_access | 非成员 size() 和更多类似物(统一容器访问) |
201411L | <iterator> <array> <deque> <forward_list> <list> <map> <regex> <set> <string> <unordered_map> <unordered_set> <vector> | (C++17) |
__cpp_lib_not_fn | std::not_fn | 201603L | <functional> | (C++17) |
__cpp_lib_null_iterators | 空遗留向前迭代器 (LegacyForwardIterator) | 201304L | <iterator> | (C++14) |
__cpp_lib_optional | std::optional | 201606L | <optional> | (C++17) |
__cpp_lib_parallel_algorithm | 为 C++17 采纳并行 TS | 201603L | <algorithm> <numeric> | (C++17) |
__cpp_lib_quoted_string_io | std::quoted | 201304L | <iomanip> | (C++14) |
__cpp_lib_ranges | 范围库及有制约算法 | 201811L | <algorithm> <functional> <iterator> <memory> <ranges> | (C++20) |
__cpp_lib_raw_memory_algorithms | 扩展内存管理工具 | 201606L | <memory> | (C++17) |
__cpp_lib_result_of_sfinae | std::result_of 与 SFINAE | 201210L | <functional> <type_traits> | (C++14) |
__cpp_lib_robust_nonmodifying_seq_ops | 使不修改序列的操作更稳健( std::mismatch 、 std::equal 及 std::is_permutation 的双范围重载) | 201304L | <algorithm> | (C++14) |
__cpp_lib_sample | std::sample | 201603L | <algorithm> | (C++17) |
__cpp_lib_scoped_lock | 变参 std::lock_guard (std::scoped_lock) | 201703L | <mutex> | (C++17) |
__cpp_lib_shared_mutex | std::shared_mutex (无时限) | 201505L | <shared_mutex> | (C++17) |
__cpp_lib_shared_ptr_arrays | std::shared_ptr<T[]> | 201611L | <memory> | (C++17) |
__cpp_lib_shared_ptr_weak_type | shared_ptr::weak_type | 201606L | <memory> | (C++17) |
__cpp_lib_shared_timed_mutex | 重命名 shared_mutex 为 shared_timed_mutex |
201402L | <shared_mutex> | (C++14) |
__cpp_lib_string_udls | 字符串类型的用户定义字面量 | 201304L | <string> | (C++14) |
__cpp_lib_string_view | std::string_view | 201606L | <string> <string_view> | (C++17) |
__cpp_lib_three_way_comparison | 三路比较(库支持) | 201711L | <compare> | (C++20) |
__cpp_lib_to_chars | 初等字符串转换( std::to_chars 、 std::from_chars ) | 201611L | <charconv> | (C++17) |
__cpp_lib_transformation_trait_aliases | 变换特征 (变换特征 (TransformationTrait) ) 缩略 | 201304L | <type_traits> | (C++14) |
__cpp_lib_transparent_operators | 通透运算符函数对象( std::less<> 等) | 201210L | <functional> | (C++14) |
使 std::owner_less 更灵活 (std::owner_less<void>) | 201510L | <memory> <functional> | (C++17) | |
__cpp_lib_tuple_element_t | std::tuple_element_t | 201402L | <tuple> | (C++14) |
__cpp_lib_tuples_by_type | 以类型进行元组寻址 | 201304L | <utility> <tuple> | (C++14) |
__cpp_lib_type_trait_variable_templates | 类型特征变量模板( std::is_void_v 等) | 201510L | <type_traits> | (C++17) |
__cpp_lib_uncaught_exceptions | std::uncaught_exceptions | 201411L | <exception> | (C++17) |
__cpp_lib_unordered_map_try_emplace | std::unordered_map::try_emplace 、 std::unordered_map::insert_or_assign | 201411L | <unordered_map> | (C++17) |
__cpp_lib_variant | std::variant : C++17 的类型安全联合体 | 201606L | <variant> | (C++17) |
__cpp_lib_void_t | std::void_t | 201411L | <type_traits> | (C++17) |
示例
运行此代码
#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 #if __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() { }
参阅
标准文档 6 | 功能特性测试推荐标准的官方文档 |