第3.15章: 特性测试
什么是特性测试
不同的编译器、平台和标准库支持不同的特性。 特性测试让你的程序可以在编译期适配当前可用的东西。
所有特性测试都由预处理器完成,发生在编译器 看到你的代码之前。
- 检测头文件
- 检测编译器特性
- 检测平台
- 检测 C++ 标准版本
- 检测库特性
- 检测工具链提供的 C 层宏
检测头文件:__has_include
__has_include 在包含之前检查头文件是否存在。
#if __has_include()
#include
#else
println("std::span not available");
#endif
检测 #embed:__has_embed
__has_embed 检查编译器是否支持
#embed 指令。
#if __has_embed("resource.bin")
static constexpr auto data =
#embed "resource.bin";
#else
print("embed not supported\n");
#endif
检测 C++ 标准版本:__cplusplus
宏 __cplusplus 指明编译器正在使用哪个 C++ 标准。
#if __cplusplus >= 202002L
print("C++20 or later\n");
#elif __cplusplus >= 201703L
print("C++17\n");
#else
print("older C++\n");
#endif
这个宏由编译器定义,而不是标准库。
编译器特性宏
编译器定义了若干宏,用来指明某些语言特性是否启用。
__cpp_exceptions
若启用了异常处理,则该宏已定义。
#ifdef __cpp_exceptions
print("exceptions enabled\n");
#else
print("exceptions disabled\n");
#endif
由于实现复杂度或运行时开销,许多环境完全禁用异常 ——包括 Android、WebAssembly、嵌入式系统以及操作系统内核。 我们将在后续章节中详细讨论这一点。
__cpp_rtti
若启用了运行时类型信息(RTTI),则该宏已定义。
#ifdef __cpp_rtti
print("RTTI enabled\n");
#else
print("RTTI disabled\n");
#endif
平台检测
编译器定义了若干用于识别操作系统的宏。
#ifdef _WIN32
print("Windows\n");
#endif
#ifdef __linux__
print("Linux\n");
#endif
#ifdef __APPLE__
print("macOS\n");
#endif
编译器检测
#ifdef __clang__
print("Clang\n");
#endif
#ifdef __GNUC__
print("GCC\n");
#endif
#ifdef _MSC_VER
print("MSVC\n");
#endif
检测库特性:<version> 头文件
C++ 标准库提供了形如 __cpp_feature 的特性测试宏。
这些宏指明哪些库特性可用。
它们全都定义在 <version> 头文件中。
#include
#ifdef __cpp_lib_span
print("std::span available\n");
#else
print("std::span not available\n");
#endif
特性测试宏的完整权威列表见:
检测 C 宏:features.h
你的工具链还提供了许多 C 层特性宏。它们并不是 C++ 的一部分,但会影响可移植性与底层行为。
它们通常定义在一个名为:
features.h
的头文件中。该头文件属于你的 C 库实现(glibc、musl、BSD libc 等)。它包含这样的宏:
_GNU_SOURCE_POSIX_C_SOURCE_XOPEN_SOURCE_FORTIFY_SOURCE
这些宏控制哪些 C 与 POSIX API 可用。
确切列表请查看你工具链的 features.h。
要点
- 特性测试发生在编译之前。
- __has_include / __has_embed:检测头文件与 embed 支持。
- __cplusplus:检测 C++ 语言版本。
- __cpp_exceptions / __cpp_rtti:检测编译器层面的特性。
- 平台宏:检测操作系统。
- 编译器宏:检测编译器。
- <version>:提供 C++ 标准库的特性测试宏。
- features.h:包含工具链提供的 C 层特性宏。
- cppreference 特性测试列表:
https://en.cppreference.com/w/cpp/feature_test.html