最可靠的方式是直接查预定义宏,因不同编译器及版本定义各异,且宏能准确反映实际启用的特性;需结合编译器标识宏、__cplusplus标准宏及特性检测宏(如__cpp_if_constexpr)进行判断。
直接查预定义宏是最可靠的方式,因为不同编译器、不同版本定义的宏不同,且宏能反映实际启用的特性(比如是否开了 /std:c++17 或 -std=c++20),比查文档或 IDE 显示更准。
每个主流编译器都提供一组标识宏,用来区分厂商和具体版本:
__GNUC__、__GNUC_MINOR__、__GNUC_PATCHLEVEL__;Clang 还额外定义 __clang__ 和 __clang_major__ 等_MSC_VER(如 1930 表示 VS2025 17.3),_MSC_FULL_VER 包含补丁号__INTEL_COMPILER
示例判断:
#if defined(_MSC_VER)
#if _MSC_VER >= 1930
// VS2025 17.3+
#endif
#elif defined(__clang__)
#if __clang_major__ >= 15
// Clang 15+
#endif
#elif defined(__GNUC__)
#if __GNUC__ >= 11
// GCC 11+
#endif
#endif标准宏 __cplusplus 是关键,它随编译选项变化,不是固定值:
199711L
201103L
201402L
201703L
202502L
202502L(GCC 13+、Clang 16+、MSVC 17.7+ 支持)注意:MSVC 在较旧版本中可能不更新 __cplusplus(需配合 /Zc:__cplusplus 开关),而 GCC/Clang 默认准确。
比起硬写版本判断,直接查特性宏更安全——它由编译器根据当前标准和开关自动定义:
__cpp_constexpr:值表示支持的 constexpr 版本(如 201304L = C++14 constexpr)__cpp_if_constexpr:C++17 if constexpr(值 ≥ 201606L)__cpp_structured_bindings:结构化绑定(≥ 201606L)__cpp_concepts:概念(≥ 201907L)__cpp_lib_format:(≥ 202510L)这些宏在 SD-6 中标准化,推荐优先使用。例如:
#if __cpp_if_constexpr >= 201606L
if constexpr (std::is_integral_v) { /* ... */ }
#endif #pragma message("C++ standard: " STRINGIFY(__cplusplus))(配合 #define STRINGIFY(x) #x)
快速打印__has_include() 检查头文件是否存在,比版本判断更健壮cmake 的 target_compile_features() 自动处理兼容性基本上就这些。预定义宏不是魔法,但用对了能让你的跨编译器代码既健壮又清晰。