一、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 Wolfeschlegelsteinhausenbergerdorffwelchevoralternwarengewissenhaftschaferswessenschafewarenwohlgepflegeundsorgfaltigkeitbeschutzenvonangreifendurchihrraubgierigfeindewelchevoralternzwolftausendjahresvorandieerscheinenvanderersteerdemenschderraumschiffgebrauchlichtalsseinursprungvonkraftgestartseinlangefahrthinzwischensternartigraumaufdersuchenachdiesternwelchegehabtbewohnbarplanetenkreisedrehensichundwohinderneurassevonverstandigmenschlichkeitkonntefortpflanzenundsicherfreuenanlebenslanglichfreudeundruhemitnichteinfurchtvorangreifenvonandererintelligentgeschopfsvonhinzwischensternartigraum."); // 在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年没有闰日
代码来自相关提案内容,很简单,只要接触过异常机制代码的一眼就可以看明白。
相关的标准中主要内容包括:
- 异常的处理分配不能逃逸出constexpr变量的初始化的范围(控制非瞬态异常:non-transient)
- 异常必须被捕获
- 异常不等于违规,违规不会被当成异常
- 异常对象的生命周期必须在常量求值内部
至于相关具体的异常相关细节的相关代码处理,可以参看具体的标准中的相关描述和实例说明。
四、总结
constexpr的应用看来应该是会越来越广泛,必须这也是一种很好的安全机制。而且如果能在编译期进行相关安全方式的引入,则更容易易让代码的健壮性得到保障。谁不想把相关的问题都消灭在萌芽阶段,而不愿意在线上让客户盯着完善和修改。
所谓安全,就是从一点一滴慢慢的积累起来。constexpr引入求值异常,正是其中的一点。

2万+

被折叠的 条评论
为什么被折叠?



