最可靠的方式是直接查预定义宏,因不同编译器及版本定义各异,且宏能准确反映实际启用的特性;需结合编译器标识宏、__cplusplus标准宏及特性检测宏(如__cpp_if_constexpr)进行判断。

直接查预定义宏是最可靠的方式,因为不同编译器、不同版本定义的宏不同,且宏能反映实际启用的特性(比如是否开了 /std:c++17 或 -std=c++20),比查文档或 IDE 显示更准。
查编译器身份和版本号
每个主流编译器都提供一组标识宏,用来区分厂商和具体版本:
-
GCC / Clang:用
__GNUC__、__GNUC_MINOR__、__GNUC_PATCHLEVEL__;Clang 还额外定义__clang__和__clang_major__等 -
MSVC:用
_MSC_VER(如 1930 表示 VS2022 17.3),_MSC_FULL_VER包含补丁号 -
Intel C++ Compiler:定义
__INTEL_COMPILER
示例判断:
#if defined(_MSC_VER)
#if _MSC_VER >= 1930
// VS2022 17.3+
#endif
#elif defined(__clang__)
#if __clang_major__ >= 15
// Clang 15+
#endif
#elif defined(__GNUC__)
#if __GNUC__ >= 11
// GCC 11+
#endif
#endif查 C++ 标准版本(核心宏)
标准宏 __cplusplus 是关键,它随编译选项变化,不是固定值:
立即学习“C++免费学习笔记(深入)”;
- C++98/03 →
199711L - C++11 →
201103L - C++14 →
201402L - C++17 →
201703L - C++20 →
202002L - C++23 →
202302L(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:(≥ 202110L)
这些宏在 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()自动处理兼容性
基本上就这些。预定义宏不是魔法,但用对了能让你的跨编译器代码既健壮又清晰。










