C++提供了很多feature test macros,即功能特性测试宏,用于在预处理阶段检查编译器是否支持某种功能,根据是否支持采取不同的操作。
测试宏一般分为如下几类:
- 某头文件是否存在
__has_include
- 属性attribute是否存在
- 语言功能特性
- 标准库功能特性
测试宏返回值对应于相应功能特性被包含到工作草案时的年份与月份的整数字面量,如果不存在不支持则返回0。
查询头文件是否存在
__has_include
用于查询头文件是否存在,成功返回1,失败返回0。比如如下示例:
#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
查询属性是否存在
__has_cpp_attribute(属性记号)
用于查询指定的属性是否被编译器支持,成功返回年月份字面量。
属性记号如下:
属性记号 | 属性 | 值 | 标准 |
---|---|---|---|
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) |
201907L | (C++20) | ||
noreturn | [[noreturn]] | 200809L | (C++11) |
unlikely | [[unlikely]] | 201803L | (C++20) |
示例如下:
#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();
查询语言和标准库特性
可查询的特性太多,请查阅https://zh.cppreference.com/w/cpp/feature_test