Skip to content

Commit

Permalink
fixed the noexception specification for connect and connect_all
Browse files Browse the repository at this point in the history
  • Loading branch information
dietmarkuehl committed Dec 21, 2024
1 parent 734df0c commit cd50ced
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 19 deletions.
37 changes: 31 additions & 6 deletions include/beman/execution26/detail/connect.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,39 @@ namespace beman::execution26::detail {
* \internal
*/
struct connect_t {
private:
template <typename Sender, typename Receiver>
auto operator()(Sender&& sender, Receiver&& receiver) const noexcept(true /*-dk:TODO*/) {
static auto make_new_sender(Sender&& sender, Receiver&& receiver) noexcept(true) -> decltype(auto) {
return ::beman::execution26::transform_sender(
decltype(::beman::execution26::detail::get_domain_late(::std::forward<Sender>(sender),
::beman::execution26::get_env(receiver))){},
::std::forward<Sender>(sender),
::beman::execution26::get_env(receiver));
}
template <typename Sender, typename Receiver>
static constexpr auto connect_noexcept() -> bool {
if constexpr (requires {
make_new_sender(::std::declval<Sender>(), ::std::declval<Receiver>())
.connect(::std::declval<Receiver>());
}) {
return noexcept(make_new_sender(::std::declval<Sender>(), ::std::declval<Receiver>())
.connect(::std::declval<Receiver>()));
} else if constexpr (requires {
::beman::execution26::detail::connect_awaitable(
make_new_sender(::std::declval<Sender>(), ::std::declval<Receiver>()),
::std::declval<Receiver>());
}) {
return noexcept(::beman::execution26::detail::connect_awaitable(
make_new_sender(::std::declval<Sender>(), ::std::declval<Receiver>()), ::std::declval<Receiver>()));
}
return true;
}

public:
template <typename Sender, typename Receiver>
auto operator()(Sender&& sender, Receiver&& receiver) const noexcept(connect_noexcept<Sender, Receiver>()) {
auto new_sender = [&sender, &receiver]() -> decltype(auto) {
return ::beman::execution26::transform_sender(
decltype(::beman::execution26::detail::get_domain_late(::std::forward<Sender>(sender),
::beman::execution26::get_env(receiver))){},
::std::forward<Sender>(sender),
::beman::execution26::get_env(receiver));
return make_new_sender(::std::forward<Sender>(sender), ::std::forward<Receiver>(receiver));
};

if constexpr (requires { new_sender().connect(::std::forward<Receiver>(receiver)); }) {
Expand Down
58 changes: 45 additions & 13 deletions include/beman/execution26/detail/connect_all.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <beman/execution26/detail/basic_state.hpp>
#include <beman/execution26/detail/product_type.hpp>
#include <beman/execution26/detail/sender_decompose.hpp>
#include <beman/execution26/detail/forward_like.hpp>
#include <cstddef>
#include <tuple>
#include <utility>
Expand All @@ -25,24 +26,55 @@ namespace beman::execution26::detail {
* \internal
*/
struct connect_all_t {
private:
template <typename Fun, typename Tuple, ::std::size_t... I>
static auto apply_with_index_helper(::std::index_sequence<I...> seq, Fun&& fun, Tuple&& tuple) noexcept(noexcept(
::std::forward<Fun>(fun)(seq, ::beman::execution26::detail::forward_like<Tuple>(::std::get<I>(tuple))...)))
-> decltype(auto) {
return ::std::forward<Fun>(fun)(seq,
::beman::execution26::detail::forward_like<Tuple>(::std::get<I>(tuple))...);
}
template <typename Fun, typename Tuple>
static auto apply_with_index(Fun&& fun, Tuple&& tuple) noexcept(
noexcept(apply_with_index_helper(::std::make_index_sequence<::std::tuple_size_v<::std::decay_t<Tuple>>>{},
::std::forward<Fun>(fun),
::std::forward<Tuple>(tuple)))) -> decltype(auto) {
return apply_with_index_helper(::std::make_index_sequence<::std::tuple_size_v<::std::decay_t<Tuple>>>{},
::std::forward<Fun>(fun),
::std::forward<Tuple>(tuple));
}

template <typename Sender, typename Receiver>
struct connect_helper {
::beman::execution26::detail::basic_state<Sender, Receiver>* op;

template <::std::size_t... J, typename... C>
auto operator()(::std::index_sequence<J...>, C&&... c) noexcept(
(noexcept(::beman::execution26::connect(
::beman::execution26::detail::forward_like<Sender>(c),
::beman::execution26::detail::basic_receiver<Sender, Receiver, ::std::integral_constant<::size_t, J>>{
this->op})) &&
... && true)) -> decltype(auto) {
return ::beman::execution26::detail::product_type{::beman::execution26::connect(
::beman::execution26::detail::forward_like<Sender>(c),
::beman::execution26::detail::basic_receiver<Sender, Receiver, ::std::integral_constant<::size_t, J>>{
this->op})...};
}
};

static auto use(auto&&...) {}

public:
//-dk:TODO is the S parameter deviating from the spec?
template <typename Sender, typename S, typename Receiver, ::std::size_t... I>
auto operator()(::beman::execution26::detail::basic_state<Sender, Receiver>* op,
S&& sender,
::std::index_sequence<I...>) const noexcept(true /*-dk:TODO*/) {
auto data{::beman::execution26::detail::get_sender_data(::std::forward<S>(sender))};
return ::std::apply(
[&op](auto&&... c) {
return [&op]<::std::size_t... J>(::std::index_sequence<J...>, auto&&... c) {
use(op);
return ::beman::execution26::detail::product_type{::beman::execution26::connect(
::beman::execution26::detail::forward_like<Sender>(c),
::beman::execution26::detail::
basic_receiver<Sender, Receiver, ::std::integral_constant<::size_t, J>>{op})...};
}(::std::make_index_sequence<::std::tuple_size_v<::std::decay_t<decltype(data.children)>>>{}, c...);
},
data.children);
::std::index_sequence<I...>) const
noexcept(noexcept(apply_with_index(
connect_helper<Sender, Receiver>{op},
::beman::execution26::detail::get_sender_data(::std::forward<S>(sender)).children))) -> decltype(auto) {
return apply_with_index(connect_helper<Sender, Receiver>{op},
::beman::execution26::detail::get_sender_data(::std::forward<S>(sender)).children);
}
};

Expand Down

0 comments on commit cd50ced

Please sign in to comment.