如何确定C++模板函数split_apply()是否满足noexcept要求
首先我们可以明确你实现的split_apply里所有操作的异常来源,在假设std::apply具备符合语义的noexcept说明符的前提下,计算规则如下:
- 首先确认无异常的代码段:你定义的
splitlambda本身已经标记了noexcept,其内部的static_assert是编译期检查不涉及运行时抛出,用到的std::get、std::forward_as_tuple、std::make_tuple均为对输入参数的引用转发/构造,无内存分配或其他抛出操作,因此整个拆分逻辑运行时不会抛出异常。 - 唯一可能的异常来源:拆分参数后,对每一段长度为M的参数块调用
std::apply(f, 块)的操作。整个split_apply不抛出的充要条件是:所有拆分得到的参数块调用std::apply(f, 块)的操作都不抛出异常。
对应的noexcept说明符可以直接按如下方式写,完全匹配运行时的异常逻辑:
template <std::size_t M> constexpr void split_apply(auto f, auto&& ...a) noexcept(noexcept( std::apply( [&](auto&&... t) noexcept(noexcept((std::apply(f, std::forward<decltype(t)>(t)), ...))) { (std::apply(f, std::forward<decltype(t)>(t)), ...); }, std::declval<decltype(split.template operator()<M>(std::forward_as_tuple(std::forward<decltype(a)>(a)...)))>() ) )) { // 原有实现 }
如果希望简化写法,因为拆分逻辑已经保证无异常,也可以直接提取核心判断条件(依赖C++20及以上标准支持):
template <std::size_t M> constexpr void split_apply(auto f, auto&& ...a) noexcept( []<std::size_t... I>(std::index_sequence<I...>) noexcept { return (noexcept(std::apply(f, std::get<I>( split.template operator()<M>(std::forward_as_tuple(std::forward<decltype(a)>(a)...)) )) && ...); }(std::make_index_sequence<sizeof...(a)/M>()) ) { // 原有实现 }
内容的提问来源于stack exchange,提问作者user1095108
相关产品推荐
相关产品推荐

