为什么这段C++代码可在Visual Studio编译,却在GCC、Clang上编译失败?
问题根因
- 你遇到的报错是C++标准的明确要求:
static_assert(false)中的条件是不依赖任何模板参数的常量表达式,编译器可以在模板定义阶段(无需等待模板实例化)直接对该表达式求值,发现值为false就直接触发断言。 if constexpr的丢弃分支(也就是条件不成立的分支)只会延迟依赖模板参数的表达式的检查,非依赖型表达式不受这个规则保护,编译器可以在解析模板的时候就直接处理。- MSVC(Visual Studio的C++编译器)的默认实现没有遵循该标准规则,它会延迟所有静态断言的检查到模板实例化阶段,所以你的代码在没调用
orTogether函数的时候不会触发报错,而GCC、Clang严格遵循标准,因此直接在模板定义阶段就报错。
修复方法
把else分支的静态断言修改为依赖模板参数的条件即可,两种常用写法:
- 直接复用之前的判断逻辑:
else { static_assert(std::is_enum_v<first_arg_type> || std::is_integral_v<first_arg_type>, "types must be either enum or integral"); }
- 用依赖模板参数的假值:
else { // sizeof的结果依赖模板参数,会推迟到实例化阶段求值 static_assert(sizeof(first_arg_type) == 0, "types must be either enum or integral"); }
修改后只有当你用既不是枚举也不是整数的类型调用orTogether函数时,才会触发断言,符合设计预期。
内容的提问来源于stack exchange,提问作者Zebrafish
相关产品推荐
相关产品推荐

