C++带constexpr、noexcept约束的构造函数中switch default分支如何处理
C++ constexpr noexcept构造函数中switch default分支的处理方案
结合你给出的constexpr、noexcept两个约束条件,有以下几种可行的处理方案,优先级从高到低排列:
方案1:区分编译期/运行期分支处理(C++20及以上推荐)
利用C++20引入的std::is_constant_evaluated()判断当前是否处于编译期求值上下文,分别做不同处理:
- 编译期执行时触发编译错误,从源头拦截非法输入
- 运行期告知编译器该分支不可达,无额外性能开销
修改后的代码示例如下:
#include <type_traits> #include <stdexcept> enum LengthUnit { MILLIMETERS = 0, MICROMETERS, NANOMETERS, }; class Length { public: constexpr Length(double value, LengthUnit unit) noexcept { switch(unit) { case MILLIMETERS: mNanometers = static_cast<int>(value * 1e6); break; case MICROMETERS: mNanometers = static_cast<int>(value * 1e3); break; case NANOMETERS: mNanometers = static_cast<int>(value); break; default: if (std::is_constant_evaluated()) { // 编译期走到该分支会直接触发编译错误,不会生成运行期代码 throw std::invalid_argument("非法的长度单位参数"); } else { // 运行期告知编译器该分支不可能走到,会被直接优化掉 // C++23可直接替换为标准库的std::unreachable() #if defined(_MSC_VER) __assume(0); #else __builtin_unreachable(); #endif } } } private: int mNanometers; };
该方案的优势:
- 完全符合
constexpr和noexcept的约束要求 - 编译期就能发现常量表达式场景下的非法输入
- 运行期无任何额外检查开销,不影响性能
方案2:模板非类型参数彻底消除非法输入(C++20及以上推荐)
如果你的使用场景中长度单位都是编译期可知的,可将单位改为构造函数的非类型模板参数,配合C++20约束直接在语法层面挡住非法输入,完全不需要default分支:
#include <concepts> enum LengthUnit { MILLIMETERS = 0, MICROMETERS, NANOMETERS, }; class Length { public: template<LengthUnit Unit> requires (Unit == MILLIMETERS || Unit == MICROMETERS || Unit == NANOMETERS) constexpr Length(double value) noexcept { if constexpr (Unit == MILLIMETERS) { mNanometers = static_cast<int>(value * 1e6); } else if constexpr (Unit == MICROMETERS) { mNanometers = static_cast<int>(value * 1e3); } else { mNanometers = static_cast<int>(value); } } private: int mNanometers; };
该方案的优势:
- 编译期直接禁止非法单位参数传入,不存在运行期非法输入的可能
- 不需要switch分支,编译器优化效果更好
方案3:兼容旧标准的终止方案(C++11及以上可用)
如果需要兼容C++20之前的标准,可以直接在default分支调用std::abort(),该函数是noexcept的,符合你的约束要求:
#include <cstdlib> // 其余代码不变 default: std::abort(); // 运行期走到该分支直接终止程序,无异常抛出
该方案的优势是兼容性好,运行期如果真的传入非法参数会直接终止程序,避免出现未定义行为,缺点是有极微小的运行期检查开销。
内容的提问来源于stack exchange,提问作者Victor Hugo
相关产品推荐
相关产品推荐

