c++26新功能—支持常量求值抛出异常

一、constexpr的异常应用

在C++的开发中,其实还是不建议大家使用异常来控制程序的问题的。但标准中既然增加了异常,如无意外就会不断的将其不断的推广下去。对于运行时来说,控制异常是一种非常容易理解的事情。但由于constexpr的引入,编译期在constexpr运算时出现异常时如何处理也提到了日程上。C++26标准前,由于没有相关的标准处理,对于开发者来说,要想进行相关的处理,则必须自己实现侵入式的机制。这无论对于开发者还是维护者来说,都是一种不友好的办法。

二、处理的机制

针对上面的常量计算异常的情况,C++26中允许其抛出异常。这样,就可以把constexpr的运算处理纳入标准的异常控制体系中。当然,在某些情况下,也可以忽略一些特定的错误问题(noexcept),从而让代码变得更加友好并易于维护。看一下代码:

consteval auto hello(std::string_view input) {
    if (input.empty()) {
        throw invalid_argument{"empty name provided"}; //当执行到throw表达式时,在此处发生编译时错误
    }

    return concat_into_a_fixed_string("hello ",input);
}
const auto a = hello(""); // 在调用处发生编译时错误,提示"empty name provided"
const auto b = hello("Hana");

try {
    const auto c = hello(""); // 此异常被捕获
} catch (const validation_error &) {
    // 正常
}

const auto d = hello("Adolph Blaine Charles David Earl Frederick Gerald Hubert Irvin John Kenneth Lloyd Martin Nero Oliver Paul Quincy Randolph Sherman Thomas Uncas Victor William Xerxes Yancy Zeus Wolfeschlegelsteinhausen­bergerdorff­welche­vor­altern­waren­gewissenhaft­schafers­wessen­schafe­waren­wohl­gepflege­und­sorgfaltigkeit­beschutzen­von­angreifen­durch­ihr­raubgierig­feinde­welche­vor­altern­zwolf­tausend­jahres­voran­die­erscheinen­van­der­erste­erdemensch­der­raumschiff­gebrauch­licht­als­sein­ursprung­von­kraft­gestart­sein­lange­fahrt­hinzwischen­sternartig­raum­auf­der­suchen­ach­die­stern­welche­gehabt­bewohnbar­planeten­kreise­drehen­sich­und­wohin­der­neu­rasse­von­verstandig­menschlichkeit­konnte­fortpflanzen­und­sich­erfreuen­an­lebenslanglich­freude­und­ruhe­mit­nicht­ein­furcht­vor­angreifen­von­anderer­intelligent­geschopfs­von­hinzwischen­sternartig­raum."); // 在concat函数深处的throw表达式处发生编译时错误
// 在调用处发生编译时错误,提示"too long name provided"

注:代码来自相关提案
目前来看,常量异常的实现是通过一个异常的槽(exception slot),然后通过抛出异常并进行存储,这样就可以利用标准中的异常机制进行匹配。即匹配try…catch代码块。

三、标准中异常的说明

看一看应用实际例子:

constexpr date parse_date(std::string_view input) {
    auto [correct, year, month, day] = ctre::match<"([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})">(input);

    if (!correct) {
        throw incorrect_date{input};
    }

    return build_date(year, month, day);
}

constexpr auto birthday = parse_date("1991-07-21"); // 正常
constexpr auto wrong_day = parse_date("1-2-3"); // 编译时错误:提供的错误日期"1-2-3"
constexpr auto weird_day = parse_date("2023-03-29"); // 编译时错误:2023年没有闰日

代码来自相关提案内容,很简单,只要接触过异常机制代码的一眼就可以看明白。
相关的标准中主要内容包括:

  1. 异常的处理分配不能逃逸出constexpr变量的初始化的范围(控制非瞬态异常:non-transient)
  2. 异常必须被捕获
  3. 异常不等于违规,违规不会被当成异常
  4. 异常对象的生命周期必须在常量求值内部

至于相关具体的异常相关细节的相关代码处理,可以参看具体的标准中的相关描述和实例说明。

四、总结

constexpr的应用看来应该是会越来越广泛,必须这也是一种很好的安全机制。而且如果能在编译期进行相关安全方式的引入,则更容易易让代码的健壮性得到保障。谁不想把相关的问题都消灭在萌芽阶段,而不愿意在线上让客户盯着完善和修改。
所谓安全,就是从一点一滴慢慢的积累起来。constexpr引入求值异常,正是其中的一点。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值