特性测试推荐

来自cppreference.com

为跟踪 C++ 标准的部分实现和实验特性,若实现定义特性,则特性测试推荐提供一组预处理器宏,,这给出一种简单而可移植的方式,检测所说的特性是否存在。

目录

[编辑] 函数宏

特性测试函数宏能展开于 #if#elif 的表达式。它们将被 #ifdef#ifndefdefined 处理成被定义宏,但不能用在别处。

[编辑] 寻找头文件

__has_include( header-name ) (1)

进行头文件名上的检查,以 #include 转译它所用的方式。

若找到头文件,则它展开为 1 ,否则为 0

注意: __has_include 是 C++17 的一部分。

[编辑] 属性

__has_cpp_attribute( attribute-token )

检查属性的存在。

对于标准属性,它将展开成添加属性到工作方案的年和月份,非官方的属性以非零值确定。

[编辑] 语言特性

下列宏展开成对应包含特性于工作方案时的年和月份

特性显著变更时,宏会相应地更新。


宏名 特性 头文件 标准/TS
__cpp_aggregate_bases 聚合初始化的扩展 201603 预定义 (C++17)
__cpp_aggregate_nsdmi 成员初始化器和聚合初始化 201304 预定义 (C++14)
__cpp_alias_templates 模板别名 200704 预定义 (C++11)
__cpp_aligned_new 过对齐数据的动态内存分配 201606 预定义 (C++17)
__cpp_attributes 属性 200809 预定义 (C++11)
__cpp_binary_literals C++ 核心语言中的二进制字面量 201304 预定义 (C++14)
__cpp_capture_star_this 如 [=,*this] 的 *this 的以值 lambda 捕获 201603 预定义 (C++17)
__cpp_concepts 制约与概念 201507 预定义 (概念 TS)
__cpp_constexpr constexpr 200704 预定义 (C++11)
放松 constexpr 函数上的制约/ constexpr 成员函数及隐式 const 201304 预定义 (C++14)
constexpr Lambda 201603 预定义 (C++17)
__cpp_decltype decltype 200707 预定义 (C++11)
__cpp_decltype_auto 正常函数的返回类型推导 201304 预定义 (C++14)
__cpp_deduction_guides 类模板的模板实参推导 201606 预定义 (C++17)
类模板实参推导相配合的 NB 决议和问题 201611 预定义 (C++17)
__cpp_delegating_constructors 委托构造函数 200604 预定义 (C++11)
__cpp_enumerator_attributes 枚举项的属性 201411 预定义 (C++17)
__cpp_exceptions 异常处理 199711 预定义 (C++98)
__cpp_fold_expressions 折叠表达式 201411 预定义 (C++17)
一元折叠与空参数包 201603 预定义 (C++17)
__cpp_generic_lambdas 泛型(多态) lambda 表达式 201304 预定义 (C++14)
__cpp_hex_float 十六进制浮点字面量 201603 预定义 (C++17)
__cpp_if_constexpr constexpr if 201606 预定义 (C++17)
__cpp_inheriting_constructors 继承构造函数 200802 预定义 (C++11)
重述继承构造函数 201511 预定义 (C++17)
__cpp_init_captures 通用化的 lambda 捕获 201304 预定义 (C++14)
__cpp_initializer_lists 初始化器列表 200806 预定义 (C++11)
__cpp_inline_variables inline 变量 201606 预定义 (C++17)
__cpp_lambdas Lambda 表达式 200907 预定义 (C++11)
__cpp_lib_addressof_constexpr constexpr std::addressof 201603 <memory> (C++17)
__cpp_lib_allocator_traits_is_always_equal std::allocator_traits::is_always_equal 201411 <memory> <scoped_allocator> <string> <deque> <forward_list> <list> <vector> <map> <set> <unordered_map> <unordered_set> (C++17)
__cpp_lib_any 库基础 V1 TS 组件: any 201603 <any> (C++17)
__cpp_lib_apply 库基础 V1 TS 组件: apply 201603 <tuple> (C++17)
__cpp_lib_array_constexpr 添加 constexpr 修饰符到 std::reverse_iteratorstd::move_iteratorstd::array范围访问 201603 <iterator> <array> (C++17)
__cpp_lib_as_const std:as_const 201510 <utility> (C++17)
__cpp_lib_atomic_is_always_lock_free constexpr atomic<T>::is_always_lock_free 201603 <atomic> (C++17)
__cpp_lib_bool_constant std::bool_constant 201505 <type_traits> (C++17)
__cpp_lib_boyer_moore_searcher 库基础 V1 TS 组件:搜索器 (Searcher) 201603 <functional> (C++17)
__cpp_lib_byte byte 类型定义 201603 <cstddef> (C++17)
__cpp_lib_chrono std::chrono::durationstd::chrono::time_point 的舍入函数 201510 <chrono> (C++17)
std::chrono::durationstd::chrono::time_point 的所有成员函数为 constexpr 201611 <chrono> (C++17)
__cpp_lib_chrono_udls 时间类型的用户定义字面量 201304 <chrono> (C++14)
__cpp_lib_clamp 在一对边界值间“夹”住值的算法( std::clamp 201603 <algorithm> (C++17)
__cpp_lib_complex_udls std::complex 的用户定义字面量 201309 <complex> (C++14)
__cpp_lib_enable_shared_from_this 重启用 shared_from_this 201603 <memory> (C++17)
__cpp_lib_exchange_function exchange() 工具函数 201304 <utility> (C++14)
__cpp_lib_experimental_any any 201411 <experimental/any> (库基础 TS)
__cpp_lib_experimental_apply apply() 以来自 tuple 的参数调用函数 201402 <experimental/tuple> (库基础 TS)
__cpp_lib_experimental_boyer_moore_searching 扩展 std::search 以使用附加的搜索算法 201411 <experimental/functional> (库基础 TS)
__cpp_lib_experimental_filesystem 文件系统库 201406 <experimental/filesystem> (文件系统 TS)
__cpp_lib_experimental_function_erased_allocator std::function 的类型擦除分配器 201406 <experimental/functional> (库基础 TS)
__cpp_lib_experimental_invocation_type 调用类型特性 201406 <experimental/type_traits> (库基础 TS)
__cpp_lib_experimental_memory_resources 多态内存资源 201402 <experimental/memory_resource> (库基础 TS)
__cpp_lib_experimental_optional optional 对象 201411 <experimental/optional> (库基础 TS)
__cpp_lib_experimental_packaged_task_erased_allocator std::packaged_task 的类型擦除分配器 201406 <experimental/future> (库基础 TS)
__cpp_lib_experimental_promise_erased_allocator std::promise 的类型擦除分配器 201406 <experimental/future> (库基础 TS)
__cpp_lib_experimental_sample sample 201402 <experimental/algorithm> (库基础 TS)
__cpp_lib_experimental_shared_ptr_arrays 扩展 shared_ptr 以支持数组 201406 <experimental/memory> (库基础 TS)
__cpp_lib_experimental_string_view string_view :到字符串的不占有引用 201411 <experimental/string_view> (库基础 TS)
__cpp_lib_experimental_type_trait_variable_templates 类型特性的变量模板 201402 <experimental/type_traits> (库基础 TS)
__cpp_lib_filesystem 为 C++17 采用文件系统 TS 201603 <filesystem> (C++17)
__cpp_lib_gcd 库基础 V2 组件: std::gcd 201606 <numeric> (C++17)
__cpp_lib_generic_associative_lookup 添加异质比较查找到关联容器 201304 <map> <set> (C++14)
__cpp_lib_hardware_interference_size constexpr std::hardware_{constructive, destructive}_interference_size 201703 <new> (C++17)
__cpp_lib_has_unique_object_representations std::has_unique_object_representations 201606 <type_traits> (C++17)
__cpp_lib_hypot 引入 3 参数重载到 std::hypot 201603 <cmath> (C++17)
__cpp_lib_incomplete_container_elements 标准容器的最小不完整类型支持 201505 (C++17)
__cpp_lib_integer_sequence 编译时整数数列 201304 <utility> (C++14)
__cpp_lib_integral_constant_callable std::integral_constant::operator() 201304 <type_traits> (C++14)
__cpp_lib_invoke std::invoke 函数模板 201411 <functional> (C++17)
__cpp_lib_is_aggregate std::is_aggregate 类型特性 201703 <type_traits> (C++17)
__cpp_lib_is_final std::is_final 201402 <type_traits> (C++14)
__cpp_lib_is_invocable std::is_invocablestd::invoke_result 201703 <type_traits> (C++17)
__cpp_lib_is_swappable [nothrow-]swappable 特性 201603 <type_traits> (C++17)
__cpp_lib_is_null_pointer std::is_null_pointer 201309 <type_traits> (C++14)
__cpp_lib_launder 核心问题 1776 :含引用成员的类对象替换( std::launder 201606 <new> (C++17)
__cpp_lib_lcm 库基础 V2 组件: std::lcm 201606 <numeric> (C++17)
__cpp_lib_logical_traits 逻辑运算符类型特性 201510 <type_traits> (C++17)
__cpp_lib_make_from_tuple make_from_tuple :为构造而应用 201606 <tuple> (C++17)
__cpp_lib_make_unique std::make_unique 201304 <memory> (C++14)
__cpp_lib_make_reverse_iterator std::make_reverse_iterator 201402 <iterator> (C++14)
__cpp_lib_map_try_emplace std::map::try_emplace, std::map::insert_or_assign 201411 <map> (C++17)
__cpp_lib_math_special_functions C++17 的数学特殊函数 201603 <cmath> (C++17)
__cpp_lib_memory_resource 库基础 V1 TS 组件: memory_resource 201603 <memory_resource> (C++17)
__cpp_lib_node_extract 接合 map 及 set ( std::map::extractstd::map::mergestd::map::insert(node_type) 等) 201606 <map> <set> <unordered_map> <unordered_set> (C++17)
__cpp_lib_nonmember_container_access 非成员 size() 及更多(统一容器访问 201411 <iterator> <array> <deque> <forward_list> <list> <map> <regex> <set> <string> <unordered_map> <unordered_set> <vector> (C++17)
__cpp_lib_not_fn 为 C++17 从库基础 2 接纳 not_fn 201603 <functional> (C++17)
__cpp_lib_null_iterators 向前迭代器 (ForwardIterator) 201304 <iterator> (C++14)
__cpp_lib_experimental_parallel_algorithm 并行扩展 201505 <experimental/algorithm> <experimental/exception_list> <experimental/execution_policy> <experimental/numeric> (并行 TS)
__cpp_lib_optional 库基础 V1 TS 组件: optional 201603 <optional> (C++17)
__cpp_lib_parallel_algorithm 为 C++17 接纳并行 TS 201603 <algorithm> <numeric> (C++17)
__cpp_lib_quoted_string_io std::quoted 201304 <iomanip> (C++14)
__cpp_lib_result_of_sfinae std::result_of 和 SFINAE 201210 <type_traits> (C++14)
__cpp_lib_robust_nonmodifying_seq_ops 令不修改序列的操作更稳健( std::mismatchstd::equalstd::is_permutation 的双范围重载) 201304 <algorithm> (C++14)
__cpp_lib_sample 库基础 V1 TS 组件: sample 201603 <algorithm> (C++17)
__cpp_lib_scoped_lock 变长 std::lock_guardstd::scoped_lock 201703 <mutex> (C++17)
__cpp_lib_shared_mutex std::shared_mutex (无时限) 201505 <shared_mutex> (C++17)
__cpp_lib_shared_ptr_arrays 库基础 V1 TS 组件: shared_ptr<T[]> 201603 <memory> (C++17)
对 shared_ptr 对数组支持的修复 201611 <memory> (C++17)
__cpp_lib_shared_ptr_weak_type shared_ptr::weak_type 201606 <memory> (C++17)
__cpp_lib_shared_timed_mutex 重命名 shared_mutexshared_timed_mutex 201402 <shared_mutex> (C++14)
__cpp_lib_string_udls 字符串类型的用户定义字面量 201304 <string> (C++14)
__cpp_lib_string_view 库基础 V1 TS 组件: string_view 201603 <string_view> (C++17)
__cpp_lib_to_chars 初等字符串转换( std::to_charsstd::from_chars 201611 <utility> (C++17)
__cpp_lib_transformation_trait_aliases 变换特性 (TransformationTrait) 消除冗余 201304 <type_traits> (C++14)
__cpp_lib_tuple_element_t 一致的元函数别名 201402 <utility> (C++14)
__cpp_lib_tuples_by_type 用类型对 tuple 寻址 201304 <utility> (C++14)
__cpp_lib_transparent_operators 制作运算符函数对象 greater<> 201210 <functional> (C++14)
std::owner_less 更灵活( std::owner_less<void> 201510 <memory> <functional> (C++17)
__cpp_lib_type_trait_variable_templates 为 C++17 从库基础 TS 接纳类型特性变量模板( std::is_void_v 等) 201510 <type_traits> (C++17)
__cpp_lib_uncaught_exceptions std::uncaught_exceptions 201411 <exception> (C++17)
__cpp_lib_unordered_map_try_emplace std::unordered_map::try_emplace, std::unordered_map::insert_or_assign 201411 <unordered_map> (C++17)
__cpp_lib_variant std::variant : C++17 的类型安全联合体 201606 <variant> (C++17)
__cpp_lib_void_t std::void_t 201411 <type_traits> (C++17)
__cpp_namespace_attributes 命名空间的属性 201411 预定义 (C++17)
__cpp_nested_namespace_definitions 嵌套命名空间定义 201411 预定义 (C++17)
__cpp_noexcept_function_type 令异常规定为类型系统的一部分 201510 预定义 (C++17)
__cpp_nontype_template_args 允许对所有非类型模板实参求值 201411 预定义 (C++17)
__cpp_nsdmi 非静态数据成员初始化器 200809 预定义 (C++11)
__cpp_range_based_for 范围 for 循环 200907 预定义 (C++11)
通用化的基于范围的 for 循环 201603 预定义 (C++17)
__cpp_raw_strings 未处理字符串字面量 200710 预定义 (C++11)
__cpp_ref_qualifiers 引用限定符 200710 预定义 (C++11)
__cpp_return_type_deduction 正常函数的返回类型推导 201304 预定义 (C++14)
__cpp_rtti 运行时类型鉴别( dynamic_casttypeid 199711 预定义 (C++98)
__cpp_rvalue_references 右值引用 200610 预定义 (C++11)
__cpp_sized_deallocation 具大小的解分配 201309 预定义 (C++14)
__cpp_static_assert static_assert 200410 预定义 (C++11)
扩展的 static_assert 201411 预定义 (C++17)
__cpp_structured_bindings 结构化绑定 201606 预定义 (C++17)
__cpp_template_auto 以 auto 声明非类型模板形参 201606 预定义 (C++17)
__cpp_template_template_args 模板模板实参的匹配 201611 预定义 (C++17)
__cpp_threadsafe_static_init 带并发的动态初始化和析构 200806 预定义 (C++11)
__cpp_transactional_memory 事务性内存 201505 预定义 (TM TS)
__cpp_unicode_characters 新字符类型char16_tchar32_t 200704 预定义 (C++11)
__cpp_unicode_literals Unicode 字符串字面量 200710 预定义 (C++11)
__cpp_user_defined_literals 用户定义字面量 200809 预定义 (C++11)
__cpp_variable_templates 变量模板 201304 预定义 (C++14)
__cpp_variadic_templates 变长模板 200704 预定义 (C++11)
__cpp_variadic_using using 声明中的包展开 201611 预定义 (C++17)
__lib_cpp_execution 为 C++17 接纳并行 TS 201603 <execution> (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
 
#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
#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 特性测试推荐上的官方文档