【发布时间】:2021-11-01 19:15:07
【问题描述】:
我有这个转发函数,它可能会抛出也可能不会抛出,这取决于参数是什么:
template <std::size_t M>
constexpr void split_apply(auto f, auto&& ...a) // noexcept(?)
{
// transforms provided tuple t into a tuple of N-element tuples
constexpr auto split([]<std::size_t N>(auto&& t) noexcept requires (bool(N))
{
constexpr auto n(std::tuple_size_v<std::remove_cvref_t<decltype(t)>>);
static_assert(n && !(n % N));
return [&]<auto ...I>(std::index_sequence<I...>) noexcept
{
return std::make_tuple(
[&]<auto ...J>(std::index_sequence<J...>) noexcept
{
constexpr auto K(N * I);
return std::forward_as_tuple(std::get<K + J>(t)...);
}(std::make_index_sequence<N + I - I>())...
);
}(std::make_index_sequence<n / N>());
}
);
std::apply([&](auto&& ...t) noexcept(noexcept(
(std::apply(f, std::forward<decltype(t)>(t)), ...)))
{
(std::apply(f, std::forward<decltype(t)>(t)), ...);
},
split.template operator()<M>(std::forward_as_tuple(a...))
);
}
由于std::apply() 没有noexcept 说明符(IMO 缺陷),因此这里可能也不应该有任何说明符,但我们假设它有一个。我如何计算 split_apply() 是否会抛出一些提供的参数?
【问题讨论】:
-
我不知道是否有帮助,但
noexcept是签名的一部分,例如给定void f() noexcept;,然后static_assert(std::is_same_v<decltype(f), void()noexcept>);通过,但static_assert(std::is_same_v<decltype(f), void()>);没有。也许你可以if constexpr以某种方式? -
noexceptoperator 执行编译时检查,如果声明表达式不引发任何异常,则返回 true。它可以在函数模板的noexcept说明符中使用,以声明函数将为某些类型抛出异常,但不会为其他类型抛出异常。 -
我想我需要澄清我想要什么,
std::apply()没有noexcept说明符,但std::invoke()有。我希望我的函数有一个(正确的)noexcept说明符,就像std::invoke()一样。有时std::invoke()是noexcept,有时不是。 -
noexcept(std::is_nothrow_invocable_v<decltype(f), decltype(a)...>)呢? -
@Evg 是的,但参数包必须以某种方式拆分,结果与结果为 AND。