how to determine if split_apply() is noexcept?

Viewed 99

I have this forwarding function, that may or may not throw, depending on what the arguments are:

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...))
  );
}

Since std::apply() does not have a noexcept specifier (a defect IMO), there probably should not be any here as well, but let's assume that it had one. How would I compute whether split_apply() throws for some provided arguments?

1 Answers

The approach I took to solve this problem (in pseudo code):

constexpr bool is_nothrow_function(/*repeat arguments*/) noexcept
{
  return noexcept(
    // repeat function body
  );
}

This same approach can be taken to fix std::apply and an implementation is available on my GitHub page.

Related