From b52f28c2f3b6fbb5d132d9e122366f19d3598ad9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Tue, 14 Jan 2025 00:48:51 +0000 Subject: [PATCH] tried to reduce the uses of sender_decompose (#118) * tried to reduce the uses of sender_decompose * clang-format --- .../beman/execution26/detail/basic_sender.hpp | 7 ++-- .../beman/execution26/detail/connect_all.hpp | 39 +++++++++++++++++++ .../execution26/detail/default_impls.hpp | 12 +++++- .../beman/execution26/detail/product_type.hpp | 14 +++++++ .../execution26/detail/sender_decompose.hpp | 23 ++++------- tests/beman/execution26/CMakeLists.txt | 2 +- 6 files changed, 75 insertions(+), 22 deletions(-) diff --git a/include/beman/execution26/detail/basic_sender.hpp b/include/beman/execution26/detail/basic_sender.hpp index ce765f1e..00e4ff33 100644 --- a/include/beman/execution26/detail/basic_sender.hpp +++ b/include/beman/execution26/detail/basic_sender.hpp @@ -33,10 +33,9 @@ struct basic_sender : ::beman::execution26::detail::product_type; auto get_env() const noexcept -> decltype(auto) { - auto data{::beman::execution26::detail::get_sender_data(*this)}; - return ::std::apply( - [&data](auto&&... c) { return ::beman::execution26::detail::impls_for::get_attrs(data.data, c...); }, - data.children); + auto&& d{this->template get<1>()}; + return sub_apply<2>( + [&d](auto&&... c) { return ::beman::execution26::detail::impls_for::get_attrs(d, c...); }, *this); } template diff --git a/include/beman/execution26/detail/connect_all.hpp b/include/beman/execution26/detail/connect_all.hpp index 057bb6c7..b7a1d3d3 100644 --- a/include/beman/execution26/detail/connect_all.hpp +++ b/include/beman/execution26/detail/connect_all.hpp @@ -44,6 +44,33 @@ struct connect_all_t { ::std::forward(tuple)); } + template <::std::size_t Start, typename Fun, typename Tuple, ::std::size_t... I> + static auto sub_apply_with_index_helper(::std::index_sequence seq, Fun&& fun, Tuple&& tuple) noexcept( + noexcept(::std::forward(fun)( + seq, ::beman::execution26::detail::forward_like(tuple.template get())...))) + -> decltype(auto) { + return ::std::forward(fun)( + seq, ::beman::execution26::detail::forward_like(tuple.template get())...); + } + template <::std::size_t Start, typename Fun, typename Tuple> + requires requires { ::std::declval().size(); } + static auto sub_apply_with_index(Fun&& fun, Tuple&& tuple) noexcept(noexcept(sub_apply_with_index_helper( + ::std::make_index_sequence<::std::tuple_size_v<::std::decay_t> - Start>{}, + ::std::forward(fun), + ::std::forward(tuple)))) -> decltype(auto) { + return sub_apply_with_index_helper( + ::std::make_index_sequence<::std::tuple_size_v<::std::decay_t> - Start>{}, + ::std::forward(fun), + ::std::forward(tuple)); + } + template <::std::size_t Start, typename Fun, typename Tuple> + requires(not requires { ::std::declval().size(); }) + static auto + sub_apply_with_index(Fun&& fun, + Tuple&&) noexcept(noexcept(::std::forward(fun)(::std::make_index_sequence<0u>{}))) { + return ::std::forward(fun)(::std::make_index_sequence<0u>{}); + } + template struct connect_helper { ::beman::execution26::detail::basic_state* op; @@ -66,6 +93,18 @@ struct connect_all_t { public: //-dk:TODO is the S parameter deviating from the spec? + template + requires requires(Sender&& s) { + s.size(); + s.template get<0>(); + } + auto operator()(::beman::execution26::detail::basic_state* op, + S&& sender, + ::std::index_sequence) const + noexcept(noexcept(sub_apply_with_index<2>(connect_helper{op}, ::std::forward(sender)))) + -> decltype(auto) { + return sub_apply_with_index<2>(connect_helper{op}, ::std::forward(sender)); + } template auto operator()(::beman::execution26::detail::basic_state* op, S&& sender, diff --git a/include/beman/execution26/detail/default_impls.hpp b/include/beman/execution26/detail/default_impls.hpp index d4f44bb2..fd84eaf9 100644 --- a/include/beman/execution26/detail/default_impls.hpp +++ b/include/beman/execution26/detail/default_impls.hpp @@ -37,10 +37,18 @@ struct default_impls { }; static constexpr auto get_state = [](Sender&& sender, Receiver& receiver) noexcept -> decltype(auto) { - auto&& decompose = ::beman::execution26::detail::get_sender_data(::std::forward(sender)); + auto&& data{[&sender]() -> decltype(auto) { + if constexpr (requires { + sender.size(); + sender.template get<1>(); + }) + return sender.template get<1>(); + else + return ::beman::execution26::detail::get_sender_data(::std::forward(sender)).data; + }()}; return ::beman::execution26::detail::allocator_aware_move( - ::beman::execution26::detail::forward_like(decompose.data), receiver); + ::beman::execution26::detail::forward_like(data), receiver); }; static constexpr auto start = [](auto&, auto&, auto&... ops) noexcept -> void { (::beman::execution26::start(ops), ...); diff --git a/include/beman/execution26/detail/product_type.hpp b/include/beman/execution26/detail/product_type.hpp index b309f95c..1c43e8e8 100644 --- a/include/beman/execution26/detail/product_type.hpp +++ b/include/beman/execution26/detail/product_type.hpp @@ -112,6 +112,20 @@ template constexpr auto is_product_type(const ::beman::execution26::detail::product_type&) -> ::std::true_type { return {}; } + +template <::std::size_t Start, typename Fun, typename Tuple, ::std::size_t... I> +constexpr auto sub_apply_helper(Fun&& fun, Tuple&& tuple, ::std::index_sequence) -> decltype(auto) { + return ::std::forward(fun)(::std::forward(tuple).template get()...); +} + +template <::std::size_t Start, typename Fun, typename Tuple> +constexpr auto sub_apply(Fun&& fun, Tuple&& tuple) -> decltype(auto) { + static constexpr ::std::size_t TSize{::std::tuple_size_v<::std::remove_cvref_t>}; + static_assert(Start <= TSize); + return sub_apply_helper( + ::std::forward(fun), ::std::forward(tuple), ::std::make_index_sequence()); +} + } // namespace beman::execution26::detail namespace std { diff --git a/include/beman/execution26/detail/sender_decompose.hpp b/include/beman/execution26/detail/sender_decompose.hpp index d8915f54..24d23d45 100644 --- a/include/beman/execution26/detail/sender_decompose.hpp +++ b/include/beman/execution26/detail/sender_decompose.hpp @@ -33,6 +33,8 @@ struct sender_data { Data& data; Children children; }; +template +sender_data(Tag&&, Data&, Children&&) -> sender_data; template auto get_sender_data(Sender&& sender) { @@ -49,33 +51,24 @@ auto get_sender_data(Sender&& sender) { sender.size(); }) return [&sender]<::std::size_t... I>(::std::index_sequence) { - return ::beman::execution26::detail::sender_data()), - decltype(sender.template get<1>()), - decltype(::std::tie(sender.template get<2 + I>()...))>{ + return ::beman::execution26::detail::sender_data{ sender.template get<0>(), sender.template get<1>(), ::std::tie(sender.template get<2 + I>()...)}; }(::std::make_index_sequence<::std::decay_t::size() - 2u>{}); else if constexpr (requires { sender_type{at, at, at, at, at, at}; }) { auto&& [tag, data, c0, c1, c2, c3] = sender; - return ::beman::execution26::detail:: - sender_data{ - tag, data, ::std::tie(c0, c1, c2, c3)}; + return ::beman::execution26::detail::sender_data{tag, data, ::std::tie(c0, c1, c2, c3)}; } else if constexpr (requires { sender_type{at, at, at, at, at}; }) { auto&& [tag, data, c0, c1, c2] = sender; - return ::beman::execution26::detail:: - sender_data{ - tag, data, ::std::tie(c0, c1, c2)}; + return ::beman::execution26::detail::sender_data{tag, data, ::std::tie(c0, c1, c2)}; } else if constexpr (requires { sender_type{at, at, at, at}; }) { auto&& [tag, data, c0, c1] = sender; - return ::beman::execution26::detail::sender_data{ - tag, data, ::std::tie(c0, c1)}; + return ::beman::execution26::detail::sender_data{tag, data, ::std::tie(c0, c1)}; } else if constexpr (requires { sender_type{at, at, at}; }) { auto&& [tag, data, c0] = sender; - return ::beman::execution26::detail::sender_data{ - tag, data, ::std::tie(c0)}; + return ::beman::execution26::detail::sender_data{tag, data, ::std::tie(c0)}; } else if constexpr (requires { sender_type{at, at}; }) { auto&& [tag, data] = sender; - return ::beman::execution26::detail::sender_data>{ - tag, data, ::std::tuple<>()}; + return ::beman::execution26::detail::sender_data{tag, data, ::std::tuple<>()}; } else { return ::beman::execution26::detail::sender_meta{}; } diff --git a/tests/beman/execution26/CMakeLists.txt b/tests/beman/execution26/CMakeLists.txt index b9130f6e..56a8d1c8 100644 --- a/tests/beman/execution26/CMakeLists.txt +++ b/tests/beman/execution26/CMakeLists.txt @@ -129,7 +129,7 @@ foreach(test ${execution_tests}) add_test(NAME ${TEST_EXE} COMMAND $) endforeach() -if(NOT PROJECT_IS_TOP_LEVEL) +if(ROJECT_IS_TOP_LEVEL) # test if the targets are findable from the build directory # cmake-format: off add_test(NAME find-package-test