You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 20:18:03