如何在无类型推导场景下触发C++ static_assert失败(或类似编译错误)
如何在无类型推导场景下触发C++ static_assert失败(或类似编译错误)
这个场景我之前折腾过好一阵!当你用constexpr替代#define写if constexpr分支链,想在最后那个兜底的else里强制触发编译失败时,直接写static_assert(false)肯定不行——编译器会直接判定这个断言永远为假,哪怕它在理论上不可达的else分支里,很多编译器(比如GCC、Clang)都会直接报错,根本不给你留机会。
那该怎么办呢?这里有个靠谱的小技巧,用一个依赖模板参数的“永远为假”的常量,哪怕你没有实际的类型推导场景也能凑出来:
首先定义一个简单的模板常量:
template <typename T = void> constexpr bool always_false_v = false;
然后在你的if constexpr兜底分支里用它:
constexpr bool is_windows = /* 你的OS判断常量表达式 */; constexpr bool is_linux = /* 你的OS判断常量表达式 */; if constexpr (is_windows) { // Windows 专属逻辑 } else if constexpr (is_linux) { // Linux 专属逻辑 } else { static_assert(always_false_v<>, "不支持当前操作系统!"); }
为啥这个方法管用?因为这是一个模板常量,编译器没办法提前确定有没有其他地方对它做了特化(哪怕你自己没写),所以它只会在这个else分支被实例化的时候,才会去检查always_false_v<>的值——而如果前面的if constexpr分支已经匹配成功,这个兜底的else根本不会被实例化,自然不会触发断言;只有当所有前面的分支都不匹配时,才会触发编译错误,完全符合你的需求。
如果你不想额外定义模板常量,还有个等价的写法,直接在分支里用一个临时的模板类:
else { template <typename T> struct always_false : std::false_type {}; static_assert(always_false<void>::value, "非法分支触发!"); }
效果是一样的,核心就是让static_assert的条件依赖于一个模板实体,避免编译器在解析阶段就直接报错。
备注:内容来源于stack exchange,提问作者ryan0270
相关产品推荐
相关产品推荐

