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

来自cppreference.com
< cpp

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

目录

[编辑] 属性

__has_cpp_attribute( attribute-token )

检查属性的存在。

对于标准属性,它将展开成该属性被添加到工作草案中时的年份和月份(见下表),特定于厂商的属性则以某个非零值确定。

能在 #if#elif 的表达式中展开 __has_cpp_attribute#ifdef#ifndefdefined 把它当做已定义的宏,但不能在别处使用它。

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_tchar32_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_iteratorstd::move_iteratorstd::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::durationstd::chrono::time_point 的舍入函数 201510L <chrono> (C++17)
std::chrono::durationstd::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::gcdstd::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_invocablestd::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_liststd::listremove()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 拼拆 mapsetstd::map::extractstd::map::mergestd::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::mismatchstd::equalstd::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_mutexshared_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_charsstd::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_emplacestd::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 功能特性测试推荐标准的官方文档