最稳妥方式是让编译器自身报告版本:GCC/Clang用__VERSION__字符串字面量,MSVC用_MSC_FULL_VER拆解,运行时执行g++ --version等命令更可信;特性判断应优先用__has_feature或__cpp_lib_*宏而非版本号。

没有“完整版本对照表全集”这种东西——C++ 标准不规定宏名、不绑定编译器版本号,所有所谓“对照表”都是人为整理的观测结果,且随编译器小版本更新可能新增、废弃或行为变更。直接查 __VERSION__ 或调用编译器命令更可靠。
怎么安全获取当前编译器名称和版本字符串
依赖宏判断版本容易漏掉补丁号或被预定义宏误导(比如 __clang_major__ 在 Apple Clang 下不反映真实 LLVM 版本)。最稳妥的方式是让编译器自己报:
- Clang/GCC:
__VERSION__是字符串字面量,如"14.0.6 (clang-1406.0.27.1)"或"13.2.0",可直接用于日志或编译期静态断言(需配合constexpr字符串解析) - MSVC:
_MSC_VER是整数(如 1938 表示 VS 2022 17.8),但无法直接推出补丁号;_MSC_FULL_VER包含完整数字(如 193833135),需自行拆解 - 运行时确认:在构建脚本中执行
g++ --version、clang++ --version或cl /?,比预处理宏更可信
常见编译器识别宏及典型值(仅作参考,勿硬编码匹配)
这些宏由编译器注入,但命名无标准,值也非线性递增。例如 GCC 12 和 GCC 13 都定义 __GNUC__ == 12?错——GCC 13 定义 __GNUC__ == 13,但某些嵌入式工具链会伪造该值。
- GCC 系:
__GNUC__、__GNUC_MINOR__、__GNUC_PATCHLEVEL__—— 可靠,但仅限真正 GCC;MinGW-w64 或 Cray 编译器可能兼容但值不准 - Clang:
__clang__(始终为 1)、__clang_major__、__clang_minor__、__clang_patchlevel__—— Apple Clang 常把__clang_major__设为 13/14,实际底层 LLVM 是 15/16,不可用于判断优化特性支持 - MSVC:
_MSC_VER(必需)、_MSC_FULL_VER(推荐)、_MSC_BUILD(补丁级,但意义模糊)—— 注意:VS 2019 16.11 和 16.12 的_MSC_VER都是 1929,必须靠_MSC_FULL_VER区分 - Intel ICX/ICPC:
__INTEL_COMPILER已弃用,应优先检测__INTEL_LLVM_COMPILER(值为类似 20230101 的日期码,非版本号)
为什么不能写“if GCC >= 12 &&
因为不同编译器对同一 C++20 特性的支持节奏不一致,且宏值不反映实际能力。比如 std::span 在 GCC 10 已可用,Clang 12 才完整支持,而 MSVC 19.29(VS 2019 16.11)就已支持——但你若只看 __clang_major__ >= 12,会在 Clang 12.0.0 上误判为可用,实际它缺 constexpr 支持。
立即学习“C++免费学习笔记(深入)”;
- 正确做法:用
__has_feature(Clang)、__has_builtin(Clang/GCC)、__has_include(跨编译器)探测具体特性,而非版本号 - 例如判断
std::format是否可用:#if __has_include(<format>) && (__cpp_lib_format >= 202302L),而不是#if __GNUC__ >= 13 - MSVC 没有
__has_feature,得查__cpp_lib_*宏 + 官方文档确认最低_MSC_VER要求
真正关键的不是“当前是什么版本”,而是“这个特性现在能不能用”。版本宏只是辅助线索,不是判决依据。越想靠宏穷举所有组合,越容易在下一个 patch 更新后失效。


















