From 3fb1236f42e39fe2a94ab44edb64c1ea161bbc80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Sun, 11 Aug 2024 22:32:44 +0100 Subject: [PATCH 01/29] added some components needed for sender concepts --- docs/questions.md | 3 + .../Beman/Execution26/detail/empty_env.hpp | 16 +++ .../detail/get_completion_signatures.hpp | 19 +++ .../Execution26/detail/get_domain_late.hpp | 18 +++ include/Beman/Execution26/detail/get_env.hpp | 3 +- .../Execution26/detail/query_with_default.hpp | 36 +++++ include/Beman/Execution26/detail/sender.hpp | 49 +++++++ .../Execution26/detail/sender_decompose.hpp | 73 ++++++++++ .../Beman/Execution26/detail/sender_for.hpp | 24 ++++ include/Beman/Execution26/execution.hpp | 1 + src/Beman/Execution26/tests/CMakeLists.txt | 3 + .../allocator-requirements-general.pass.cpp | 4 +- .../tests/exec-getcomplsigs.pass.cpp | 17 +++ .../tests/exec-snd-concepts.pass.cpp | 126 ++++++++++++++++++ .../Execution26/tests/exec-snd-expos.pass.cpp | 49 +++++++ .../tests/stoptoken-concepts.pass.cpp | 2 +- 16 files changed, 438 insertions(+), 5 deletions(-) create mode 100644 include/Beman/Execution26/detail/empty_env.hpp create mode 100644 include/Beman/Execution26/detail/get_completion_signatures.hpp create mode 100644 include/Beman/Execution26/detail/get_domain_late.hpp create mode 100644 include/Beman/Execution26/detail/query_with_default.hpp create mode 100644 include/Beman/Execution26/detail/sender.hpp create mode 100644 include/Beman/Execution26/detail/sender_decompose.hpp create mode 100644 include/Beman/Execution26/detail/sender_for.hpp create mode 100644 src/Beman/Execution26/tests/exec-getcomplsigs.pass.cpp create mode 100644 src/Beman/Execution26/tests/exec-snd-concepts.pass.cpp create mode 100644 src/Beman/Execution26/tests/exec-snd-expos.pass.cpp diff --git a/docs/questions.md b/docs/questions.md index 86eaf434..f6cd256e 100644 --- a/docs/questions.md +++ b/docs/questions.md @@ -15,3 +15,6 @@ likely observable. - [exec.fwd.env] states "Mandates: ... is a core constant expression if `q` is a core constant expression": I don't know how to possibly implement that. +- [exec.snd.expos] uses query-or-default; it seems only query-with-default + is defined. +- [exec.snd.concepts] "The type tag_of_t is +defined+ as follows:" diff --git a/include/Beman/Execution26/detail/empty_env.hpp b/include/Beman/Execution26/detail/empty_env.hpp new file mode 100644 index 00000000..ed41626f --- /dev/null +++ b/include/Beman/Execution26/detail/empty_env.hpp @@ -0,0 +1,16 @@ +// include/Beman/Execution26/detail/empty_env.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_EMPTY_ENV +#define INCLUDED_BEMAN_EXECUTION26_DETAIL_EMPTY_ENV + +// ---------------------------------------------------------------------------- + +namespace Beman::Execution26 +{ + struct empty_env {}; +} + +// ---------------------------------------------------------------------------- + +#endif diff --git a/include/Beman/Execution26/detail/get_completion_signatures.hpp b/include/Beman/Execution26/detail/get_completion_signatures.hpp new file mode 100644 index 00000000..5b5c9518 --- /dev/null +++ b/include/Beman/Execution26/detail/get_completion_signatures.hpp @@ -0,0 +1,19 @@ +// include/Beman/Execution26/detail/get_completion_signatures.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_GET_COMPLETION_SIGNATURES +#define INCLUDED_BEMAN_EXECUTION26_DETAIL_GET_COMPLETION_SIGNATURES + +// ---------------------------------------------------------------------------- + +namespace Beman::Execution26 +{ + struct get_completion_signatures_t + { + }; + inline constexpr get_completion_signatures_t get_completion_signatures{}; +} + +// ---------------------------------------------------------------------------- + +#endif diff --git a/include/Beman/Execution26/detail/get_domain_late.hpp b/include/Beman/Execution26/detail/get_domain_late.hpp new file mode 100644 index 00000000..cd55982f --- /dev/null +++ b/include/Beman/Execution26/detail/get_domain_late.hpp @@ -0,0 +1,18 @@ +// include/Beman/Execution26/detail/get_domain_late.hpp -*-C++-*- +// ---------------------------------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// ---------------------------------------------------------------------------- + +#ifndef INCLUDED_INCLUDE_BEMAN_EXECUTION26_DETAIL_GET_DOMAIN_LATE +#define INCLUDED_INCLUDE_BEMAN_EXECUTION26_DETAIL_GET_DOMAIN_LATE + +// ---------------------------------------------------------------------------- + +namespace nstd { + namespace xxx { + } +} + +// ---------------------------------------------------------------------------- + +#endif diff --git a/include/Beman/Execution26/detail/get_env.hpp b/include/Beman/Execution26/detail/get_env.hpp index 844a1aef..5f33c174 100644 --- a/include/Beman/Execution26/detail/get_env.hpp +++ b/include/Beman/Execution26/detail/get_env.hpp @@ -5,6 +5,7 @@ #define INCLUDED_BEMAN_EXECUTION26_DETAIL_GET_ENV #include +#include #include #include @@ -12,8 +13,6 @@ namespace Beman::Execution26 { - struct empty_env {}; - struct get_env_t { template diff --git a/include/Beman/Execution26/detail/query_with_default.hpp b/include/Beman/Execution26/detail/query_with_default.hpp new file mode 100644 index 00000000..ff1cf028 --- /dev/null +++ b/include/Beman/Execution26/detail/query_with_default.hpp @@ -0,0 +1,36 @@ +// include/Beman/Execution26/detail/query_with_default.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_QUERY_WITH_DEFAULT +#define INCLUDED_BEMAN_EXECUTION26_DETAIL_QUERY_WITH_DEFAULT + +#include + +// ---------------------------------------------------------------------------- + +namespace Beman::Execution26::Detail +{ + template + requires requires(Tag const& tag, Env const& env) + { + tag(env); + } + constexpr auto query_with_default(Tag, Env const& env, Value&&) + noexcept(noexcept(Tag()(env))) + -> decltype(auto) + { + return Tag()(env); + } + + template + constexpr auto query_with_default(Tag, Env const&, Value&& value) + noexcept(noexcept(static_cast(std::forward(value)))) + -> decltype(auto) + { + return static_cast(std::forward(value)); + } +} + +// ---------------------------------------------------------------------------- + +#endif diff --git a/include/Beman/Execution26/detail/sender.hpp b/include/Beman/Execution26/detail/sender.hpp new file mode 100644 index 00000000..a7ae6913 --- /dev/null +++ b/include/Beman/Execution26/detail/sender.hpp @@ -0,0 +1,49 @@ +// include/Beman/Execution26/detail/sender.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_SENDER +#define INCLUDED_BEMAN_EXECUTION26_DETAIL_SENDER + +#include +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- + +namespace Beman::Execution26 +{ + struct sender_t {}; +} +namespace Beman::Execution26::Detail +{ + template + concept is_sender + = ::std::derived_from + ; + + template + concept enable_sender + = ::Beman::Execution26::Detail::is_sender + //-dk:TODO || ::Beman::Execution26::Detail::is_awaitable> + ; +} +namespace Beman::Execution26 +{ + template + concept sender + = ::Beman::Execution26::Detail::enable_sender<::std::remove_cvref_t> + && requires(::std::remove_cvref_t const& sndr) + { + { ::Beman::Execution26::get_env(sndr) } -> ::Beman::Execution26::Detail::queryable; + } + && ::std::move_constructible<::std::remove_cvref_t> + && ::std::constructible_from<::std::remove_cvref_t, Sender> + ; +} + +// ---------------------------------------------------------------------------- + +#endif diff --git a/include/Beman/Execution26/detail/sender_decompose.hpp b/include/Beman/Execution26/detail/sender_decompose.hpp new file mode 100644 index 00000000..97bf2c01 --- /dev/null +++ b/include/Beman/Execution26/detail/sender_decompose.hpp @@ -0,0 +1,73 @@ +// include/Beman/Execution26/detail/sender_decompose.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_SENDER_DECOMPOSE +#define INCLUDED_BEMAN_EXECUTION26_DETAIL_SENDER_DECOMPOSE + +#include +#include + +// ---------------------------------------------------------------------------- + +namespace Beman::Execution26::Detail +{ + inline constexpr struct sender_any_t + { + template constexpr operator T() const; + } sender_any; + + template + struct sender_meta + { + using tag_type = ::std::remove_cvref_t; + using data_type = ::std::remove_cvref_t; + using children_type = ::std::remove_cvref_t; + }; + + template + auto get_sender_meta(Sender&& sender) + { + #if 0 + //-dk:TODO should use a dynamic/language approach: + auto&& [tag, data, ... children] = sender; + return sender_meta>; + #endif + using sender_type = ::std::remove_cvref_t; + static constexpr ::Beman::Execution26::Detail::sender_any_t any{}; + if constexpr (requires(){ sender_type{ any, any, any, any, any, any }; }) + { + auto&& [tag, data, c0, c1, c2, c3] = sender; + return ::Beman::Execution26::Detail::sender_meta>{}; + } + else if constexpr (requires(){ sender_type{ any, any, any, any, any }; }) + { + auto&& [tag, data, c0, c1, c2] = sender; + return ::Beman::Execution26::Detail::sender_meta>{}; + } + else if constexpr (requires(){ sender_type{ any, any, any, any }; }) + { + auto&& [tag, data, c0, c1] = sender; + return ::Beman::Execution26::Detail::sender_meta>{}; + } + else if constexpr (requires(){ sender_type{ any, any, any }; }) + { + auto&& [tag, data, c0] = sender; + return ::Beman::Execution26::Detail::sender_meta>{}; + } + else if constexpr (requires(){ sender_type{ any, any }; }) + { + auto&& [tag, data] = sender; + return ::Beman::Execution26::Detail::sender_meta>{}; + } + } +} + +namespace Beman::Execution26 +{ + template + using tag_of_t = typename decltype(::Beman::Execution26::Detail::get_sender_meta(::std::declval()))::tag_type; +} + +// ---------------------------------------------------------------------------- + +#endif diff --git a/include/Beman/Execution26/detail/sender_for.hpp b/include/Beman/Execution26/detail/sender_for.hpp new file mode 100644 index 00000000..6217d578 --- /dev/null +++ b/include/Beman/Execution26/detail/sender_for.hpp @@ -0,0 +1,24 @@ +// include/Beman/Execution26/detail/sender_for.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_SENDER_FOR +#define INCLUDED_BEMAN_EXECUTION26_DETAIL_SENDER_FOR + +#include +#include +#include + +// ---------------------------------------------------------------------------- + +namespace Beman::Execution26::Detail +{ + template + concept sender_for + = ::Beman::Execution26::sender + && ::std::same_as<::Beman::Execution26::tag_of_t, Tag> + ; +} + +// ---------------------------------------------------------------------------- + +#endif diff --git a/include/Beman/Execution26/execution.hpp b/include/Beman/Execution26/execution.hpp index 60ae39d0..26d2b5cd 100644 --- a/include/Beman/Execution26/execution.hpp +++ b/include/Beman/Execution26/execution.hpp @@ -7,6 +7,7 @@ // ---------------------------------------------------------------------------- #include +#include #include #include #include diff --git a/src/Beman/Execution26/tests/CMakeLists.txt b/src/Beman/Execution26/tests/CMakeLists.txt index 1e7a67e4..708cf2dc 100644 --- a/src/Beman/Execution26/tests/CMakeLists.txt +++ b/src/Beman/Execution26/tests/CMakeLists.txt @@ -2,6 +2,9 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception list(APPEND execution_tests + exec-snd-expos.pass + exec-snd-concepts.pass + exec-getcomplsigs.pass exec-get-domain.pass exec-get-stop-token.pass exec-get-allocator.pass diff --git a/src/Beman/Execution26/tests/allocator-requirements-general.pass.cpp b/src/Beman/Execution26/tests/allocator-requirements-general.pass.cpp index 86684b49..d696f9d8 100644 --- a/src/Beman/Execution26/tests/allocator-requirements-general.pass.cpp +++ b/src/Beman/Execution26/tests/allocator-requirements-general.pass.cpp @@ -45,8 +45,8 @@ namespace struct allocate_size_type_mismatch { - using value_type = int; //-dk:TODO long; - auto allocate(size_type n) -> int* { return new int[::std::size_t(n)]; } + using value_type = long; + auto allocate(::std::size_t n) -> int* { return new int[::std::size_t(n)]; } auto deallocate(int*, ::std::size_t) -> void {} auto operator== (allocate_size_type_mismatch const&) const -> bool = default; diff --git a/src/Beman/Execution26/tests/exec-getcomplsigs.pass.cpp b/src/Beman/Execution26/tests/exec-getcomplsigs.pass.cpp new file mode 100644 index 00000000..24ddd0a5 --- /dev/null +++ b/src/Beman/Execution26/tests/exec-getcomplsigs.pass.cpp @@ -0,0 +1,17 @@ +// src/Beman/Execution26/tests/exec-getcomplsigs.pass.cpp -*-C++-*- +// ---------------------------------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// ---------------------------------------------------------------------------- + +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- + +auto main() -> int +{ + static_assert(std::same_as); +} \ No newline at end of file diff --git a/src/Beman/Execution26/tests/exec-snd-concepts.pass.cpp b/src/Beman/Execution26/tests/exec-snd-concepts.pass.cpp new file mode 100644 index 00000000..94f52b06 --- /dev/null +++ b/src/Beman/Execution26/tests/exec-snd-concepts.pass.cpp @@ -0,0 +1,126 @@ +// src/Beman/Execution26/tests/exec-snd-concepts.pass.cpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- + +namespace +{ + struct non_sender {}; + + struct own_sender_t: test_std::sender_t {}; + + struct std_sender { using sender_concept = test_std::sender_t; }; + struct own_sender { using sender_concept = own_sender_t; }; + + struct tag_t {}; + struct tagged_sender + { + using sender_concept = test_std::sender_t; + tag_t tag; + int data; + }; + struct tagged_sender1 + { + using sender_concept = test_std::sender_t; + tag_t tag; + int data; + int child1; + }; + struct tagged_sender2 + { + using sender_concept = test_std::sender_t; + tag_t tag; + int data; + int child1; + int child2; + }; + struct tagged_sender3 + { + using sender_concept = test_std::sender_t; + tag_t tag; + int data; + int child1; + int child2; + int child3; + }; + struct tagged_sender4 + { + using sender_concept = test_std::sender_t; + tag_t tag; + int data; + int child1; + int child2; + int child3; + int child4; + }; + + auto test_is_sender() -> void + { + static_assert(not test_detail::is_sender); + static_assert(not test_detail::is_sender); + static_assert(not test_detail::is_sender); + static_assert(not test_detail::is_sender); + static_assert(test_detail::is_sender); + static_assert(test_detail::is_sender); + static_assert(test_detail::is_sender); + } + + auto test_enable_sender() -> void + { + static_assert(not test_detail::enable_sender); + static_assert(not test_detail::enable_sender); + static_assert(not test_detail::enable_sender); + static_assert(not test_detail::enable_sender); + static_assert(test_detail::enable_sender); + static_assert(test_detail::enable_sender); + static_assert(test_detail::enable_sender); + } + + auto test_sender() -> void + { + static_assert(not test_std::sender); + static_assert(test_std::sender); + static_assert(test_std::sender); + static_assert(test_std::sender); + static_assert(test_std::sender); + static_assert(test_std::sender); + static_assert(test_std::sender); + } + + auto test_tag_of_t() -> void + { + //auto&& [tag, data, ...children] = tagged_sender(); + static_assert(std::same_as>); + static_assert(std::same_as>); + static_assert(std::same_as>); + static_assert(std::same_as>); + static_assert(std::same_as>); + } + + auto test_sender_for() -> void + { + static_assert(test_std::sender); + static_assert(test_detail::sender_for); + static_assert(test_std::sender); + static_assert(test_detail::sender_for); + + static_assert(test_std::sender); + static_assert(not test_detail::sender_for); + }; +} + +auto main() -> int +{ + test_is_sender(); + test_enable_sender(); + test_sender(); + test_tag_of_t(); + test_sender_for(); +} \ No newline at end of file diff --git a/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp b/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp new file mode 100644 index 00000000..36844de2 --- /dev/null +++ b/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp @@ -0,0 +1,49 @@ +// src/Beman/Execution26/tests/exe-snd-expos.pass.cpp -*-C++-*- +// ---------------------------------------------------------------------------- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// ---------------------------------------------------------------------------- + +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- + +namespace +{ + struct domain + { + int value{}; + }; + struct default_domain + { + int default_value{}; + }; + + struct env + { + int value{}; + auto query(test_std::get_domain_t const&) const noexcept { return domain{value}; } + }; + + auto test_query_with_default() + { + auto result1{test_detail::query_with_default(test_std::get_domain, + env{43}, + default_domain{74})}; + static_assert(std::same_as); + assert(result1.value == 43); + + auto result2{test_detail::query_with_default(test_std::get_domain, + test_std::empty_env(), + default_domain{74})}; + static_assert(std::same_as); + assert(result2.default_value == 74); + } +} + +auto main() -> int +{ + test_query_with_default(); +} \ No newline at end of file diff --git a/src/Beman/Execution26/tests/stoptoken-concepts.pass.cpp b/src/Beman/Execution26/tests/stoptoken-concepts.pass.cpp index 9ea40d74..551cc0da 100644 --- a/src/Beman/Execution26/tests/stoptoken-concepts.pass.cpp +++ b/src/Beman/Execution26/tests/stoptoken-concepts.pass.cpp @@ -92,7 +92,7 @@ namespace stoppable_token struct non_template_callback_type { - struct callback_type {}; //-dk:TODO + struct callback_type {}; auto stop_requested() const noexcept -> bool; auto stop_possible() const noexcept -> bool; auto operator== (non_template_callback_type const&) const -> bool = default; From 8e5d6d3dd95bbd24a81c51285534eb4c1a250e54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Sat, 17 Aug 2024 21:01:22 +0100 Subject: [PATCH 02/29] added exposition-only fwd_env() --- include/Beman/Execution26/detail/fwd_env.hpp | 32 +++++++++++++++++++ .../Execution26/tests/exec-snd-expos.pass.cpp | 29 ++++++++++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 include/Beman/Execution26/detail/fwd_env.hpp diff --git a/include/Beman/Execution26/detail/fwd_env.hpp b/include/Beman/Execution26/detail/fwd_env.hpp new file mode 100644 index 00000000..9a15107a --- /dev/null +++ b/include/Beman/Execution26/detail/fwd_env.hpp @@ -0,0 +1,32 @@ +// include/Beman/Execution26/detail/fwd_env.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_FWD_ENV +#define INCLUDED_BEMAN_EXECUTION26_DETAIL_FWD_ENV + +#include +#include +#include + +// ---------------------------------------------------------------------------- + +namespace Beman::Execution26::Detail +{ + template + struct fwd_env + { + Env env; + fwd_env(Env env): env(::std::forward(env)) {} + + template + requires (::Beman::Execution26::forwarding_query(::std::remove_cvref_t())) + constexpr auto query(Query&& q, Args&&... args) const + { + return env.query(q, ::std::forward(args)...); + } + }; +} + +// ---------------------------------------------------------------------------- + +#endif diff --git a/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp b/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp index 36844de2..bde6c568 100644 --- a/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp +++ b/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp @@ -4,6 +4,7 @@ // ---------------------------------------------------------------------------- #include +#include #include #include #include @@ -21,13 +22,38 @@ namespace int default_value{}; }; + constexpr struct forwardable_t + : test_std::forwarding_query_t + { + } forwardable; + struct non_forwardable_t {}; + struct env { int value{}; auto query(test_std::get_domain_t const&) const noexcept { return domain{value}; } + auto query(non_forwardable_t const&) const noexcept { return true; } + auto query(forwardable_t const&, int a, int b) const noexcept { return (value + a) * b; } }; - auto test_query_with_default() + template + auto test_fwd_env_helper() -> void + { + env e{42}; + static_assert(Expect == requires(){ + test_detail::fwd_env(e).query(Query()); + }); + } + auto test_fwd_env() -> void + { + env e{42}; + static_assert(test_std::Detail::queryable); + test_fwd_env_helper(); + test_fwd_env_helper(); + assert(129 == test_detail::fwd_env(e).query(forwardable, 1, 3)); + } + + auto test_query_with_default() -> void { auto result1{test_detail::query_with_default(test_std::get_domain, env{43}, @@ -45,5 +71,6 @@ namespace auto main() -> int { + test_fwd_env(); test_query_with_default(); } \ No newline at end of file From cdec19d826cc18f609116f3b3a9563ce0ec54b96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Sat, 17 Aug 2024 21:23:35 +0100 Subject: [PATCH 03/29] added exposition-only make_env --- include/Beman/Execution26/detail/fwd_env.hpp | 4 ++- include/Beman/Execution26/detail/make_env.hpp | 30 +++++++++++++++++++ .../Execution26/tests/exec-snd-expos.pass.cpp | 18 +++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 include/Beman/Execution26/detail/make_env.hpp diff --git a/include/Beman/Execution26/detail/fwd_env.hpp b/include/Beman/Execution26/detail/fwd_env.hpp index 9a15107a..cabb9fd7 100644 --- a/include/Beman/Execution26/detail/fwd_env.hpp +++ b/include/Beman/Execution26/detail/fwd_env.hpp @@ -16,7 +16,7 @@ namespace Beman::Execution26::Detail struct fwd_env { Env env; - fwd_env(Env env): env(::std::forward(env)) {} + fwd_env(Env&& env): env(::std::forward(env)) {} template requires (::Beman::Execution26::forwarding_query(::std::remove_cvref_t())) @@ -25,6 +25,8 @@ namespace Beman::Execution26::Detail return env.query(q, ::std::forward(args)...); } }; + template + fwd_env(Env&&) -> fwd_env; } // ---------------------------------------------------------------------------- diff --git a/include/Beman/Execution26/detail/make_env.hpp b/include/Beman/Execution26/detail/make_env.hpp new file mode 100644 index 00000000..d8925e77 --- /dev/null +++ b/include/Beman/Execution26/detail/make_env.hpp @@ -0,0 +1,30 @@ +// include/Beman/Execution26/detail/make_env.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_MAKE_ENV +#define INCLUDED_BEMAN_EXECUTION26_DETAIL_MAKE_ENV + +#include +#include + +// ---------------------------------------------------------------------------- + +namespace Beman::Execution26::Detail +{ + template + struct make_env + { + Value value; + template + make_env(Query const&, V&& value): value(::std::forward(value)) {} + constexpr auto query(Query const&) const -> Value const& { return this->value; } + constexpr auto query(Query const&) -> Value & { return this->value; } + }; + template + make_env(Query&&, Value&& value) + -> make_env<::std::remove_cvref_t, ::std::remove_cvref_t>; +} + +// ---------------------------------------------------------------------------- + +#endif diff --git a/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp b/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp index bde6c568..f6b07261 100644 --- a/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp +++ b/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -28,6 +29,13 @@ namespace } forwardable; struct non_forwardable_t {}; + constexpr struct custom_query_t {} custom_query; + struct custom_result + { + int value; + auto operator== (custom_result const&) const -> bool = default; + }; + struct env { int value{}; @@ -53,6 +61,15 @@ namespace assert(129 == test_detail::fwd_env(e).query(forwardable, 1, 3)); } + auto test_make_env() -> void + { + auto env{test_detail::make_env(custom_query, custom_result{43})}; + auto const cenv{env}; + static_assert(test_std::Detail::queryable); + assert(env.query(custom_query) == custom_result{43}); + assert(cenv.query(custom_query) == custom_result{43}); + } + auto test_query_with_default() -> void { auto result1{test_detail::query_with_default(test_std::get_domain, @@ -72,5 +89,6 @@ namespace auto main() -> int { test_fwd_env(); + test_make_env(); test_query_with_default(); } \ No newline at end of file From c6f5effd68b77b3af9582c1a708e55726a6e899c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Sat, 17 Aug 2024 22:10:20 +0100 Subject: [PATCH 04/29] added exposition-only join_env() --- include/Beman/Execution26/detail/fwd_env.hpp | 11 ++- include/Beman/Execution26/detail/join_env.hpp | 80 +++++++++++++++++++ include/Beman/Execution26/detail/make_env.hpp | 5 +- .../Execution26/tests/exec-snd-expos.pass.cpp | 75 +++++++++++++++-- 4 files changed, 162 insertions(+), 9 deletions(-) create mode 100644 include/Beman/Execution26/detail/join_env.hpp diff --git a/include/Beman/Execution26/detail/fwd_env.hpp b/include/Beman/Execution26/detail/fwd_env.hpp index cabb9fd7..b99c4ee0 100644 --- a/include/Beman/Execution26/detail/fwd_env.hpp +++ b/include/Beman/Execution26/detail/fwd_env.hpp @@ -4,6 +4,7 @@ #ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_FWD_ENV #define INCLUDED_BEMAN_EXECUTION26_DETAIL_FWD_ENV +#include #include #include #include @@ -13,11 +14,19 @@ namespace Beman::Execution26::Detail { template - struct fwd_env + class fwd_env { + private: Env env; + + public: fwd_env(Env&& env): env(::std::forward(env)) {} + template + requires (not ::Beman::Execution26::forwarding_query(::std::remove_cvref_t())) + constexpr auto query(Query&& q, Args&&... args) const + = BEMAN_EXECUTION26_DELETE("the used query is not forwardable"); + template requires (::Beman::Execution26::forwarding_query(::std::remove_cvref_t())) constexpr auto query(Query&& q, Args&&... args) const diff --git a/include/Beman/Execution26/detail/join_env.hpp b/include/Beman/Execution26/detail/join_env.hpp new file mode 100644 index 00000000..a3178ec1 --- /dev/null +++ b/include/Beman/Execution26/detail/join_env.hpp @@ -0,0 +1,80 @@ +// include/Beman/Execution26/detail/join_env.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_JOIN_ENV +#define INCLUDED_BEMAN_EXECUTION26_DETAIL_JOIN_ENV + +#include +#include + +// ---------------------------------------------------------------------------- + +namespace Beman::Execution26::Detail +{ + template + class join_env + { + private: + Env1 env1; + Env2 env2; + + public: + template + join_env(E1&& env1, E2&& env2) + : env1(::std::forward(env1)) + , env2(::std::forward(env2)) + { + } + + template + requires + (requires(Env1&, Query const& query, Args&&... args) + { + env1.query(query, ::std::forward(args)...); + } + || requires(Env2& env2, Query const& query, Args&&... args) { + env2.query(query, ::std::forward(args)...); + } + ) + auto query(Query const& query, Args&&... args) -> decltype(auto) + { + if constexpr (requires{ env1.query(query, ::std::forward(args)...); }) + { + return env1.query(query, ::std::forward(args)...); + } + else + { + return env2.query(query, ::std::forward(args)...); + } + } + template + requires + (requires(Env1 const&, Query const& query, Args&&... args) + { + env1.query(query, ::std::forward(args)...); + } + || requires(Env2 const& env2, Query const& query, Args&&... args) { + env2.query(query, ::std::forward(args)...); + } + ) + auto query(Query const& query, Args&&... args) const -> decltype(auto) + { + if constexpr (requires{ env1.query(query, ::std::forward(args)...); }) + { + return env1.query(query, ::std::forward(args)...); + } + else + { + return env2.query(query, ::std::forward(args)...); + } + } + }; + + template + join_env(Env1&&, Env2&&) + -> join_env<::std::remove_cvref_t, ::std::remove_cvref_t>; +} + +// ---------------------------------------------------------------------------- + +#endif diff --git a/include/Beman/Execution26/detail/make_env.hpp b/include/Beman/Execution26/detail/make_env.hpp index d8925e77..d731dd19 100644 --- a/include/Beman/Execution26/detail/make_env.hpp +++ b/include/Beman/Execution26/detail/make_env.hpp @@ -12,9 +12,12 @@ namespace Beman::Execution26::Detail { template - struct make_env + class make_env { + private: Value value; + + public: template make_env(Query const&, V&& value): value(::std::forward(value)) {} constexpr auto query(Query const&) const -> Value const& { return this->value; } diff --git a/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp b/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp index f6b07261..ac0dcbe6 100644 --- a/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp +++ b/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp @@ -1,11 +1,10 @@ // src/Beman/Execution26/tests/exe-snd-expos.pass.cpp -*-C++-*- -// ---------------------------------------------------------------------------- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// ---------------------------------------------------------------------------- -#include #include #include +#include +#include #include #include #include @@ -29,7 +28,10 @@ namespace } forwardable; struct non_forwardable_t {}; - constexpr struct custom_query_t {} custom_query; + template + struct custom_query_t {}; + template + constexpr custom_query_t custom_query; struct custom_result { int value; @@ -44,6 +46,21 @@ namespace auto query(forwardable_t const&, int a, int b) const noexcept { return (value + a) * b; } }; + struct env1 + { + int value{}; + auto query(custom_query_t<0>, int a) const { return this->value + a; } + auto query(custom_query_t<1>, int a) const { return this->value + a; } + }; + + struct env2 + { + int value{}; + auto query(custom_query_t<0>, int a) const { return this->value + a; } + auto query(custom_query_t<2>, int a) const { return this->value + a; } + }; + + template auto test_fwd_env_helper() -> void { @@ -63,11 +80,54 @@ namespace auto test_make_env() -> void { - auto env{test_detail::make_env(custom_query, custom_result{43})}; + auto env{test_detail::make_env(custom_query<0>, custom_result{43})}; auto const cenv{env}; static_assert(test_std::Detail::queryable); - assert(env.query(custom_query) == custom_result{43}); - assert(cenv.query(custom_query) == custom_result{43}); + assert(env.query(custom_query<0>) == custom_result{43}); + assert(cenv.query(custom_query<0>) == custom_result{43}); + } + + template + auto test_join_env(Env&& env) -> void + { + static_assert(Expect == requires{ env.query(Query(), 17); }); + } + auto test_join_env() -> void + { + env1 e1{42}; + env1 const ce1{e1}; + env2 e2{17}; + env2 const ce2{e2}; + + test_join_env>(e1); + test_join_env>(ce1); + test_join_env>(e1); + test_join_env>(ce1); + test_join_env>(e1); + test_join_env>(ce1); + test_join_env>(e1); + test_join_env>(ce1); + test_join_env>(e2); + test_join_env>(ce2); + test_join_env>(e2); + test_join_env>(ce2); + test_join_env>(e2); + test_join_env>(ce2); + test_join_env>(e2); + test_join_env>(ce2); + + auto env{test_detail::join_env(e1, e2)}; + auto const& cenv{env}; + + static_assert(test_std::Detail::queryable); + test_join_env>(env); + test_join_env>(cenv); + test_join_env>(env); + test_join_env>(cenv); + test_join_env>(env); + test_join_env>(cenv); + test_join_env>(env); + test_join_env>(cenv); } auto test_query_with_default() -> void @@ -90,5 +150,6 @@ auto main() -> int { test_fwd_env(); test_make_env(); + test_join_env(); test_query_with_default(); } \ No newline at end of file From 5aa5622c32699454a1e82176df899b526aed8047 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Sun, 18 Aug 2024 00:35:19 +0100 Subject: [PATCH 05/29] added get_completion_scheduler, get_scheduler, sched_attrs, and sched_env --- .../Execution26/detail/forwarding_query.hpp | 3 +- .../detail/get_completion_scheduler.hpp | 46 ++++++++++ .../Execution26/detail/get_scheduler.hpp | 34 ++++++++ .../Beman/Execution26/detail/sched_attrs.hpp | 47 ++++++++++ .../Beman/Execution26/detail/sched_env.hpp | 42 +++++++++ src/Beman/Execution26/tests/CMakeLists.txt | 2 + .../tests/exec-get-compl-sched.pass.cpp | 87 +++++++++++++++++++ .../tests/exec-get-scheduler.pass.cpp | 38 ++++++++ .../Execution26/tests/exec-snd-expos.pass.cpp | 63 ++++++++++++++ 9 files changed, 361 insertions(+), 1 deletion(-) create mode 100644 include/Beman/Execution26/detail/get_completion_scheduler.hpp create mode 100644 include/Beman/Execution26/detail/get_scheduler.hpp create mode 100644 include/Beman/Execution26/detail/sched_attrs.hpp create mode 100644 include/Beman/Execution26/detail/sched_env.hpp create mode 100644 src/Beman/Execution26/tests/exec-get-compl-sched.pass.cpp create mode 100644 src/Beman/Execution26/tests/exec-get-scheduler.pass.cpp diff --git a/include/Beman/Execution26/detail/forwarding_query.hpp b/include/Beman/Execution26/detail/forwarding_query.hpp index af033545..aec1f755 100644 --- a/include/Beman/Execution26/detail/forwarding_query.hpp +++ b/include/Beman/Execution26/detail/forwarding_query.hpp @@ -5,6 +5,7 @@ #define INCLUDED_BEMAN_EXECUTION26_DETAIL_FORWARDING_QUERY #include +#include #include // ---------------------------------------------------------------------------- @@ -25,7 +26,7 @@ namespace Beman::Execution26 template constexpr auto operator()(Object&&) const noexcept -> bool { - return ::std::derived_from; + return ::std::derived_from<::std::remove_cvref_t, ::Beman::Execution26::forwarding_query_t>; } }; diff --git a/include/Beman/Execution26/detail/get_completion_scheduler.hpp b/include/Beman/Execution26/detail/get_completion_scheduler.hpp new file mode 100644 index 00000000..17113ecb --- /dev/null +++ b/include/Beman/Execution26/detail/get_completion_scheduler.hpp @@ -0,0 +1,46 @@ +// include/Beman/Execution26/detail/get_completion_scheduler.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_GET_COMPLETION_SCHEDULER +#define INCLUDED_BEMAN_EXECUTION26_DETAIL_GET_COMPLETION_SCHEDULER + +#include +#include +#include +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- + +namespace Beman::Execution26 +{ + template + struct get_completion_scheduler_t + : ::Beman::Execution26::forwarding_query_t + { + template + auto operator()(Env&& env) const noexcept + { + static_assert(noexcept(::std::as_const(env).query(*this))); + //-dk:TODO mandate result is a scheduler: + // static_assert(::Beman::Execution26::scheduler< + // decltype(::std::as_const(env).query(*this)) + // >); + return ::std::as_const(env).query(*this); + } + }; + + template + requires( + ::std::same_as + || ::std::same_as + || ::std::same_as + ) + inline constexpr get_completion_scheduler_t get_completion_scheduler{}; +} + +// ---------------------------------------------------------------------------- + +#endif diff --git a/include/Beman/Execution26/detail/get_scheduler.hpp b/include/Beman/Execution26/detail/get_scheduler.hpp new file mode 100644 index 00000000..14b24242 --- /dev/null +++ b/include/Beman/Execution26/detail/get_scheduler.hpp @@ -0,0 +1,34 @@ +// include/Beman/Execution26/detail/get_scheduler.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_GET_SCHEDULER +#define INCLUDED_BEMAN_EXECUTION26_DETAIL_GET_SCHEDULER + +#include +#include + +// ---------------------------------------------------------------------------- + +namespace Beman::Execution26 +{ + struct get_scheduler_t + : ::Beman::Execution26::forwarding_query_t + { + template + auto operator()(Env&& env) const noexcept + { + static_assert(noexcept(::std::as_const(env).query(*this))); + //-dk:TODO mandate that the result is a scheduler + // static_assert(::Beman::Execution26::scheduler< + // decltype(::std::as_const(env).query(*this)) + // >) + return ::std::as_const(env).query(*this); + } + }; + + inline constexpr get_scheduler_t get_scheduler{}; +} + +// ---------------------------------------------------------------------------- + +#endif diff --git a/include/Beman/Execution26/detail/sched_attrs.hpp b/include/Beman/Execution26/detail/sched_attrs.hpp new file mode 100644 index 00000000..f8fea096 --- /dev/null +++ b/include/Beman/Execution26/detail/sched_attrs.hpp @@ -0,0 +1,47 @@ +// include/Beman/Execution26/detail/sched_attrs.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_SCHED_ATTRS +#define INCLUDED_BEMAN_EXECUTION26_DETAIL_SCHED_ATTRS + +#include +#include +#include +#include +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- + +namespace Beman::Execution26::Detail +{ + template + class sched_attrs + { + private: + Scheduler sched; + + public: + template + sched_attrs(S&& sched): sched(::std::forward(sched)) {} + + template + auto query(::Beman::Execution26::get_completion_scheduler_t const&) const noexcept + { + return this->sched; + } + auto query(::Beman::Execution26::get_domain_t const& q) const noexcept + { + return this->sched.query(q); + } + }; + + template + sched_attrs(Scheduler&&) -> sched_attrs<::std::remove_cvref_t>; +} + +// ---------------------------------------------------------------------------- + +#endif diff --git a/include/Beman/Execution26/detail/sched_env.hpp b/include/Beman/Execution26/detail/sched_env.hpp new file mode 100644 index 00000000..b8ddcf05 --- /dev/null +++ b/include/Beman/Execution26/detail/sched_env.hpp @@ -0,0 +1,42 @@ +// include/Beman/Execution26/detail/sched_env.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_SCHED_ENV +#define INCLUDED_BEMAN_EXECUTION26_DETAIL_SCHED_ENV + +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- + +namespace Beman::Execution26::Detail +{ + template + class sched_env + { + private: + Scheduler sched; + + public: + template + sched_env(S&& sched): sched(::std::forward(sched)) {} + + auto query(::Beman::Execution26::get_scheduler_t const&) const noexcept + { + return this->sched; + } + auto query(::Beman::Execution26::get_domain_t const& q) const noexcept + { + return this->sched.query(q); + } + }; + + template + sched_env(Scheduler&&) -> sched_env<::std::remove_cvref_t>; +} + +// ---------------------------------------------------------------------------- + +#endif diff --git a/src/Beman/Execution26/tests/CMakeLists.txt b/src/Beman/Execution26/tests/CMakeLists.txt index 708cf2dc..ba734ec5 100644 --- a/src/Beman/Execution26/tests/CMakeLists.txt +++ b/src/Beman/Execution26/tests/CMakeLists.txt @@ -2,6 +2,8 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception list(APPEND execution_tests + exec-get-scheduler.pass + exec-get-compl-sched.pass exec-snd-expos.pass exec-snd-concepts.pass exec-getcomplsigs.pass diff --git a/src/Beman/Execution26/tests/exec-get-compl-sched.pass.cpp b/src/Beman/Execution26/tests/exec-get-compl-sched.pass.cpp new file mode 100644 index 00000000..db8d2eff --- /dev/null +++ b/src/Beman/Execution26/tests/exec-get-compl-sched.pass.cpp @@ -0,0 +1,87 @@ +// src/Beman/Execution26/tests/exec-get-compl-sched.pass.cpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- + +namespace +{ + struct tag {}; + + template + struct scheduler + { + int value{}; + auto operator== (scheduler const&) const -> bool = default; + }; + + struct env + { + int value{}; + auto query(test_std::get_completion_scheduler_t const&) const noexcept + { + return scheduler{this->value + 1}; + } + auto query(test_std::get_completion_scheduler_t const&) const noexcept + { + return scheduler{this->value + 2}; + } + auto query(test_std::get_completion_scheduler_t const&) const noexcept + { + return scheduler{this->value + 3}; + } + template + auto query(test_std::get_completion_scheduler_t const&) const noexcept + { + return scheduler{this->value}; + } + }; + + template + auto test_tag(Env&& env) -> void + { + static_assert(Expect == requires{ test_std::get_completion_scheduler(env); }); + } +} + +auto main() -> int +{ + static_assert(std::same_as const, + decltype(test_std::get_completion_scheduler)>); + static_assert(std::same_as const, + decltype(test_std::get_completion_scheduler)>); + static_assert(std::same_as const, + decltype(test_std::get_completion_scheduler)>); + static_assert(test_std::forwarding_query(test_std::get_completion_scheduler)); + static_assert(test_std::forwarding_query(test_std::get_completion_scheduler)); + static_assert(test_std::forwarding_query(test_std::get_completion_scheduler)); + + env e{17}; + test_tag(e); + test_tag(e); + test_tag(e); + test_tag(e); + + static_assert(::std::same_as< + decltype(test_std::get_completion_scheduler(e)), + scheduler>); + static_assert(::std::same_as< + decltype(test_std::get_completion_scheduler(e)), + scheduler>); + static_assert(::std::same_as< + decltype(test_std::get_completion_scheduler(e)), + scheduler>); + assert(test_std::get_completion_scheduler(e) + == scheduler{19}); + assert(test_std::get_completion_scheduler(e) + == scheduler{20}); + assert(test_std::get_completion_scheduler(e) + == scheduler{18}); +} \ No newline at end of file diff --git a/src/Beman/Execution26/tests/exec-get-scheduler.pass.cpp b/src/Beman/Execution26/tests/exec-get-scheduler.pass.cpp new file mode 100644 index 00000000..e6f8bad1 --- /dev/null +++ b/src/Beman/Execution26/tests/exec-get-scheduler.pass.cpp @@ -0,0 +1,38 @@ +// src/Beman/Execution26/tests/exec-get-scheduler.pass.cpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- + +namespace +{ + struct scheduler + { + int value{}; + auto operator== (scheduler const&) const -> bool = default; + }; + + struct env + { + int value{}; + auto query(test_std::get_scheduler_t const&) const noexcept + { + return scheduler{this->value}; + } + }; +} + +auto main() -> int +{ + static_assert(std::same_as); + static_assert(test_std::forwarding_query(test_std::get_scheduler)); + env e{17}; + auto sched{test_std::get_scheduler(e)}; + static_assert(::std::same_as); + assert(sched == scheduler{17}); +} \ No newline at end of file diff --git a/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp b/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp index ac0dcbe6..c1a10468 100644 --- a/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp +++ b/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include #include @@ -16,6 +18,7 @@ namespace struct domain { int value{}; + auto operator== (domain const&) const -> bool = default; }; struct default_domain { @@ -60,6 +63,15 @@ namespace auto query(custom_query_t<2>, int a) const { return this->value + a; } }; + struct scheduler + { + int value{}; + auto query(test_std::get_domain_t) const { return domain{this->value}; } + + auto operator== (scheduler const&) const -> bool = default; + }; + + // ------------------------------------------------------------------------ template auto test_fwd_env_helper() -> void @@ -128,6 +140,55 @@ namespace test_join_env>(cenv); test_join_env>(env); test_join_env>(cenv); + + assert(env.query(custom_query<0>, 13) == 55); + assert(cenv.query(custom_query<0>, 13) == 55); + assert(env.query(custom_query<1>, 13) == 55); + assert(cenv.query(custom_query<1>, 13) == 55); + assert(env.query(custom_query<2>, 13) == 30); + assert(cenv.query(custom_query<2>, 13) == 30); + } + + auto test_sched_attrs() -> void + { + scheduler sched{17}; + assert(sched.query(test_std::get_domain) == domain{17}); + + auto attrs{test_detail::sched_attrs(sched)}; + static_assert(test_detail::queryable); + + auto sched_error{attrs.query(test_std::get_completion_scheduler)}; + static_assert(::std::same_as); + assert(sched_error == sched); + + auto sched_stopped{attrs.query(test_std::get_completion_scheduler)}; + static_assert(::std::same_as); + assert(sched_stopped == sched); + + auto sched_value{attrs.query(test_std::get_completion_scheduler)}; + static_assert(::std::same_as); + assert(sched_value == sched); + + auto dom{attrs.query(test_std::get_domain)}; + static_assert(::std::same_as); + assert(dom == domain{17}); + } + + auto test_sched_env() -> void + { + scheduler sched{17}; + assert(sched.query(test_std::get_domain) == domain{17}); + + auto env{test_detail::sched_env(sched)}; + static_assert(test_detail::queryable); + + auto qsched{env.query(test_std::get_scheduler)}; + static_assert(::std::same_as); + assert(qsched == sched); + + auto dom{env.query(test_std::get_domain)}; + static_assert(::std::same_as); + assert(dom == domain{17}); } auto test_query_with_default() -> void @@ -151,5 +212,7 @@ auto main() -> int test_fwd_env(); test_make_env(); test_join_env(); + test_sched_attrs(); + test_sched_env(); test_query_with_default(); } \ No newline at end of file From dec9ddfab0989042216631e96c5fe0cdf182bb3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Sun, 18 Aug 2024 21:44:45 +0100 Subject: [PATCH 06/29] added default_domain --- .../Beman/Execution26/detail/continues_on.hpp | 21 ++ .../Execution26/detail/default_domain.hpp | 87 +++++++ .../detail/get_completion_signatures.hpp | 3 +- .../Execution26/detail/get_domain_late.hpp | 29 ++- .../Execution26/detail/sender_decompose.hpp | 4 + src/Beman/Execution26/tests/CMakeLists.txt | 1 + .../tests/exec-domain-default.pass.cpp | 216 ++++++++++++++++++ .../tests/exec-getcomplsigs.pass.cpp | 1 + .../tests/exec-snd-concepts.pass.cpp | 12 + .../Execution26/tests/exec-snd-expos.pass.cpp | 17 ++ 10 files changed, 384 insertions(+), 7 deletions(-) create mode 100644 include/Beman/Execution26/detail/continues_on.hpp create mode 100644 include/Beman/Execution26/detail/default_domain.hpp create mode 100644 src/Beman/Execution26/tests/exec-domain-default.pass.cpp diff --git a/include/Beman/Execution26/detail/continues_on.hpp b/include/Beman/Execution26/detail/continues_on.hpp new file mode 100644 index 00000000..6a8fe60d --- /dev/null +++ b/include/Beman/Execution26/detail/continues_on.hpp @@ -0,0 +1,21 @@ +// include/Beman/Execution26/detail/continues_on.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_CONTINUES_ON +#define INCLUDED_BEMAN_EXECUTION26_DETAIL_CONTINUES_ON + +// ---------------------------------------------------------------------------- + +namespace Beman::Execution26 +{ + struct continues_on_t + { + //-dk:TODO provide actual implementation + }; + + inline constexpr continues_on_t continues_on{}; +} + +// ---------------------------------------------------------------------------- + +#endif diff --git a/include/Beman/Execution26/detail/default_domain.hpp b/include/Beman/Execution26/detail/default_domain.hpp new file mode 100644 index 00000000..13067499 --- /dev/null +++ b/include/Beman/Execution26/detail/default_domain.hpp @@ -0,0 +1,87 @@ +// include/Beman/Execution26/detail/default_domain.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_DEFAULT_DOMAIN +#define INCLUDED_BEMAN_EXECUTION26_DETAIL_DEFAULT_DOMAIN + +#include +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- + +namespace Beman::Execution26 +{ + struct default_domain + { + template <::Beman::Execution26::sender Sender, + ::Beman::Execution26::Detail::queryable... Env> + requires (sizeof...(Env) <= 1) + && requires(Sender&& sender, Env&&... env) + { + ::Beman::Execution26::tag_of_t().transform_sender(::std::forward(sender), ::std::forward(env)...); + } + static constexpr auto transform_sender(Sender&& sender, Env&&... env) + noexcept(noexcept(::Beman::Execution26::tag_of_t().transform_sender(::std::forward(sender), ::std::forward(env)...))) + -> ::Beman::Execution26::sender decltype(auto) + { + return ::Beman::Execution26::tag_of_t().transform_sender(::std::forward(sender), ::std::forward(env)...); + } + + template <::Beman::Execution26::sender Sender, + ::Beman::Execution26::Detail::queryable... Env> + requires (sizeof...(Env) <= 1) + && (not requires(Sender&& sender, Env&&... env) + { + ::Beman::Execution26::tag_of_t().transform_sender(::std::forward(sender), ::std::forward(env)...); + }) + static constexpr auto transform_sender(Sender&& sender, Env&&...) + noexcept(noexcept(::std::forward(sender))) + -> ::Beman::Execution26::sender decltype(auto) + { + return ::std::forward(sender); + } + + template <::Beman::Execution26::sender Sender, + ::Beman::Execution26::Detail::queryable Env> + requires requires(Sender&& sender, Env&& env) + { + ::Beman::Execution26::tag_of_t().transform_env(::std::forward(sender), ::std::forward(env)); + } + static constexpr auto transform_env(Sender&& sender, Env&& env) noexcept + -> ::Beman::Execution26::Detail::queryable decltype(auto) + { + return ::Beman::Execution26::tag_of_t().transform_env(::std::forward(sender), ::std::forward(env)); + } + + template <::Beman::Execution26::sender Sender, + ::Beman::Execution26::Detail::queryable Env> + requires (not requires(Sender&& sender, Env&& env) + { + ::Beman::Execution26::tag_of_t().transform_env(::std::forward(sender), ::std::forward(env)); + }) + static constexpr auto transform_env(Sender&&, Env&& env) noexcept + -> ::Beman::Execution26::Detail::queryable decltype(auto) + { + return static_cast(::std::forward(env)); + } + + template + requires requires(Sender&& sender, Args&&... args) + { + Tag().apply_sender(::std::forward(sender), ::std::forward(args)...); + } + static constexpr auto apply_sender(Tag, Sender&& sender, Args&&... args) + noexcept(noexcept(Tag().apply_sender(::std::forward(sender), ::std::forward(args)...))) + -> decltype(auto) + { + return Tag().apply_sender(::std::forward(sender), ::std::forward(args)...); + } + }; +} + +// ---------------------------------------------------------------------------- + +#endif diff --git a/include/Beman/Execution26/detail/get_completion_signatures.hpp b/include/Beman/Execution26/detail/get_completion_signatures.hpp index 5b5c9518..d3ad8879 100644 --- a/include/Beman/Execution26/detail/get_completion_signatures.hpp +++ b/include/Beman/Execution26/detail/get_completion_signatures.hpp @@ -10,10 +10,11 @@ namespace Beman::Execution26 { struct get_completion_signatures_t { + //-dk:TODO add implementation }; inline constexpr get_completion_signatures_t get_completion_signatures{}; } // ---------------------------------------------------------------------------- -#endif +#endif \ No newline at end of file diff --git a/include/Beman/Execution26/detail/get_domain_late.hpp b/include/Beman/Execution26/detail/get_domain_late.hpp index cd55982f..81130d37 100644 --- a/include/Beman/Execution26/detail/get_domain_late.hpp +++ b/include/Beman/Execution26/detail/get_domain_late.hpp @@ -1,15 +1,32 @@ // include/Beman/Execution26/detail/get_domain_late.hpp -*-C++-*- -// ---------------------------------------------------------------------------- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// ---------------------------------------------------------------------------- -#ifndef INCLUDED_INCLUDE_BEMAN_EXECUTION26_DETAIL_GET_DOMAIN_LATE -#define INCLUDED_INCLUDE_BEMAN_EXECUTION26_DETAIL_GET_DOMAIN_LATE +#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_GET_DOMAIN_LATE +#define INCLUDED_BEMAN_EXECUTION26_DETAIL_GET_DOMAIN_LATE + +// #include +#include +#include // ---------------------------------------------------------------------------- -namespace nstd { - namespace xxx { +namespace Beman::Execution26::Detail +{ + template + struct get_domain_late_helper + { + template + static constexpr auto get(Sender const& sender, Env const& env) noexcept + { + (void)sender; (void)env; + return ::Beman::Execution26::default_domain(); + } + }; + template + constexpr auto get_domain_late(Sender const& sender, Env const& env) noexcept + { + using tag_t = ::Beman::Execution26::tag_of_t; + return ::Beman::Execution26::Detail::get_domain_late_helper::get(sender, env); } } diff --git a/include/Beman/Execution26/detail/sender_decompose.hpp b/include/Beman/Execution26/detail/sender_decompose.hpp index 97bf2c01..273f934e 100644 --- a/include/Beman/Execution26/detail/sender_decompose.hpp +++ b/include/Beman/Execution26/detail/sender_decompose.hpp @@ -59,6 +59,10 @@ namespace Beman::Execution26::Detail auto&& [tag, data] = sender; return ::Beman::Execution26::Detail::sender_meta>{}; } + else + { + return ::Beman::Execution26::Detail::sender_meta{}; + } } } diff --git a/src/Beman/Execution26/tests/CMakeLists.txt b/src/Beman/Execution26/tests/CMakeLists.txt index ba734ec5..3c3c2140 100644 --- a/src/Beman/Execution26/tests/CMakeLists.txt +++ b/src/Beman/Execution26/tests/CMakeLists.txt @@ -2,6 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception list(APPEND execution_tests + exec-domain-default.pass exec-get-scheduler.pass exec-get-compl-sched.pass exec-snd-expos.pass diff --git a/src/Beman/Execution26/tests/exec-domain-default.pass.cpp b/src/Beman/Execution26/tests/exec-domain-default.pass.cpp new file mode 100644 index 00000000..6ceb5181 --- /dev/null +++ b/src/Beman/Execution26/tests/exec-domain-default.pass.cpp @@ -0,0 +1,216 @@ +// src/Beman/Execution26/tests/exec-domain-default.pass.cpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- + +namespace +{ + struct env + { + int value{}; + auto operator== (env const&) const -> bool = default; + }; + struct tagged_env + { + int value{}; + auto operator== (tagged_env const&) const -> bool = default; + }; + + struct non_sender {}; + struct simple_sender + { + using sender_concept = test_std::sender_t; + int value{}; + auto operator== (simple_sender const&) const -> bool = default; + }; + + struct simple_tag {}; + + template + struct tag + { + template + auto transform_sender(Sender&& sender, Env&&...) noexcept(Noexcept) + { + return simple_sender{sender.value}; + } + + template + auto transform_env(Sender&&, Env&& e) noexcept + { + return env{e.value}; + } + + template + auto apply_sender(Sender&&, int value) noexcept(Noexcept) + { + return value; + } + template + auto apply_sender(Sender&&, int v0, int v1, int v2) noexcept(Noexcept) + { + return v0 + v1 + v2; + } + template + auto apply_sender(Sender&&, bool& flag) noexcept(Noexcept) -> bool& + { + return flag; + } + }; + + template + struct tagged_sender + { + using sender_concept = test_std::sender_t; + tag t{}; + int value{17}; + int args{}; + }; + + template + auto test_transform_sender(Domain) + { + static_assert(test_detail::queryable); + static_assert(test_std::sender); + static_assert(not requires{ Domain::transform_sender(non_sender{}); }); + static_assert(requires{ Domain::transform_sender(simple_sender{}); }); + static_assert(requires{ Domain::transform_sender(simple_sender{}, env{}); }); + static_assert(not requires{ Domain::transform_sender(simple_sender{}, env{}, env{}); }); + static_assert(noexcept(Domain::transform_sender(simple_sender{}))); + static_assert(noexcept(Domain::transform_sender(simple_sender{}, env{}))); + using simple_rvalue_type = decltype(Domain::transform_sender(simple_sender{})); + static_assert(std::same_as); + using simple_env_rvalue_type = decltype(Domain::transform_sender(simple_sender{}, env{})); + static_assert(std::same_as); + simple_sender sender; + using simple_lvalue_type = decltype(Domain::transform_sender(sender)); + static_assert(std::same_as); + using simple_env_lvalue_type = decltype(Domain::transform_sender(sender, env{})); + static_assert(std::same_as); + simple_sender const csender; + using simple_clvalue_type = decltype(Domain::transform_sender(csender)); + static_assert(std::same_as); + using simple_env_clvalue_type = decltype(Domain::transform_sender(csender, env{})); + static_assert(std::same_as); + + assert(simple_sender{17} == Domain::transform_sender(simple_sender{17}, env{})); + assert(&sender == &Domain::transform_sender(sender, env{})); + assert(&csender == &Domain::transform_sender(csender, env{})); + + static_assert(test_std::sender>); + static_assert(test_std::sender>); + static_assert(std::same_as, test_std::tag_of_t>>); + static_assert(std::same_as, test_std::tag_of_t>>); + static_assert(requires{ tag().transform_sender(tagged_sender()); }); + static_assert(requires{ tag().transform_sender(tagged_sender(), env{}); }); + static_assert(requires{ tag().transform_sender(tagged_sender()); }); + static_assert(requires{ tag().transform_sender(tagged_sender(), env{}); }); + static_assert(requires{ Domain::transform_sender(tagged_sender()); }); + static_assert(requires{ Domain::transform_sender(tagged_sender(), env{}); }); + static_assert(not requires{ Domain::transform_sender(tagged_sender(), env{}, env{}); }); + static_assert(requires{ Domain::transform_sender(tagged_sender()); }); + static_assert(requires{ Domain::transform_sender(tagged_sender(), env{}); }); + static_assert(not requires{ Domain::transform_sender(tagged_sender(), env{}, env{}); }); + static_assert(noexcept(Domain::transform_sender(tagged_sender()))); + static_assert(noexcept(Domain::transform_sender(tagged_sender(), env{}))); + static_assert(not noexcept(Domain::transform_sender(tagged_sender()))); + static_assert(not noexcept(Domain::transform_sender(tagged_sender(), env{}))); + { + using type = decltype(Domain::transform_sender(tagged_sender())); + static_assert(std::same_as); + assert(simple_sender{17} == Domain::transform_sender(tagged_sender())); + } + { + using type = decltype(Domain::transform_sender(tagged_sender(), env{})); + static_assert(std::same_as); + assert(simple_sender{17} == Domain::transform_sender(tagged_sender(), env{})); + } + { + using type = decltype(Domain::transform_sender(tagged_sender())); + static_assert(std::same_as); + assert(simple_sender{17} == Domain::transform_sender(tagged_sender())); + } + { + using type = decltype(Domain::transform_sender(tagged_sender(), env{})); + static_assert(std::same_as); + assert(simple_sender{17} == Domain::transform_sender(tagged_sender(), env{})); + } + //-dk:TODO test returning a non-sender doesn't work + } + + template + auto test_transform_env(Domain) + { + static_assert(test_detail::queryable); + static_assert(test_std::sender); + static_assert(requires{ Domain::transform_env(simple_sender{}, env{}); }); + static_assert(noexcept(Domain::transform_env(simple_sender{}, env{}))); + { + using type = decltype(Domain::transform_env(simple_sender{}, env{})); + static_assert(std::same_as); + assert(env{17} == Domain::transform_env(simple_sender{}, env{17})); + } + { + env e{17}; + using type = decltype(Domain::transform_env(simple_sender{}, e)); + static_assert(std::same_as); + assert(&e == &Domain::transform_env(simple_sender{}, e)); + } + { + env const ce{17}; + using type = decltype(Domain::transform_env(simple_sender{}, ce)); + static_assert(std::same_as); + assert(&ce == &Domain::transform_env(simple_sender{}, ce)); + } + + static_assert(test_std::sender>); + static_assert(requires{ tag{}.transform_env(tagged_sender(), env{}); }); + static_assert(std::same_as{}.transform_env(tagged_sender(), env{}))>); + static_assert(requires{ Domain::transform_env(tagged_sender{}, env{}); }); + static_assert(noexcept(Domain::transform_env(tagged_sender{}, env{}))); + { + using type = decltype(Domain::transform_env(tagged_sender{}, env{})); + static_assert(std::same_as); + assert(env{17} == Domain::transform_env(simple_sender{}, env{17})); + } + } + + template + auto test_apply_sender(Domain) -> void + { + static_assert(test_std::sender); + static_assert(not requires{ Domain().apply_sender(simple_tag{}, simple_sender{}); }); + static_assert(not requires{ Domain().apply_sender(simple_tag{}, simple_sender{}, 0); }); + + static_assert(not requires{ Domain().apply_sender(tag{}, simple_sender{}); }); + static_assert(requires{ Domain().apply_sender(tag{}, simple_sender{}, 0); }); + static_assert(not requires{ Domain().apply_sender(tag{}, simple_sender{}, 0, 0); }); + static_assert(requires{ Domain().apply_sender(tag{}, simple_sender{}, 0, 0, 0); }); + static_assert(noexcept(Domain().apply_sender(tag{}, simple_sender{}, 0))); + static_assert(noexcept(Domain().apply_sender(tag{}, simple_sender{}, 0, 0, 0))); + static_assert(not noexcept(Domain().apply_sender(tag{}, simple_sender{}, 0))); + static_assert(not noexcept(Domain().apply_sender(tag{}, simple_sender{}, 0, 0, 0))); + + assert(17 == Domain().apply_sender(tag{}, simple_sender{}, 17)); + assert(15 == Domain().apply_sender(tag{}, simple_sender{}, 4, 5, 6)); + + bool flag{}; + assert(&flag == &Domain().apply_sender(tag{}, simple_sender{}, flag)); + } +} + +// ---------------------------------------------------------------------------- + +auto main() -> int +{ + test_std::default_domain domain{}; + test_transform_sender(domain); + test_transform_env(domain); + test_apply_sender(domain); +} \ No newline at end of file diff --git a/src/Beman/Execution26/tests/exec-getcomplsigs.pass.cpp b/src/Beman/Execution26/tests/exec-getcomplsigs.pass.cpp index 24ddd0a5..c0128eec 100644 --- a/src/Beman/Execution26/tests/exec-getcomplsigs.pass.cpp +++ b/src/Beman/Execution26/tests/exec-getcomplsigs.pass.cpp @@ -14,4 +14,5 @@ auto main() -> int { static_assert(std::same_as); + //-dk:TODO add actual tests } \ No newline at end of file diff --git a/src/Beman/Execution26/tests/exec-snd-concepts.pass.cpp b/src/Beman/Execution26/tests/exec-snd-concepts.pass.cpp index 94f52b06..73044789 100644 --- a/src/Beman/Execution26/tests/exec-snd-concepts.pass.cpp +++ b/src/Beman/Execution26/tests/exec-snd-concepts.pass.cpp @@ -61,6 +61,17 @@ namespace int child4; }; + // ------------------------------------------------------------------------- + + auto test_valid_completion_signatures() + { + static_assert(not test_detail::valid_completion_signatures); + static_assert(test_detail::valid_completion_signatures< + test_std::completion_signatures<>>); + static_assert(test_detail::valid_completion_signatures< + test_std::completion_signatures>); + } + auto test_is_sender() -> void { static_assert(not test_detail::is_sender); @@ -118,6 +129,7 @@ namespace auto main() -> int { + test_valid_completion_signatures(); test_is_sender(); test_enable_sender(); test_sender(); diff --git a/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp b/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp index c1a10468..9574489d 100644 --- a/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp +++ b/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp @@ -6,7 +6,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -63,6 +65,11 @@ namespace auto query(custom_query_t<2>, int a) const { return this->value + a; } }; + struct test_sender + { + using sender_concept = test_std::sender_t; + }; + struct scheduler { int value{}; @@ -205,6 +212,15 @@ namespace static_assert(std::same_as); assert(result2.default_value == 74); } + + auto test_get_domain_late() -> void + { + static_assert(test_std::sender); + env const e; + test_sender const sndr; + auto dom{test_detail::get_domain_late(sndr, e)}; + (void)dom; + } } auto main() -> int @@ -215,4 +231,5 @@ auto main() -> int test_sched_attrs(); test_sched_env(); test_query_with_default(); + test_get_domain_late(); } \ No newline at end of file From b7fd2a59a6793d542ec74d0c747c758c87f1106e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Mon, 19 Aug 2024 22:29:47 +0100 Subject: [PATCH 07/29] added schedule and scheduler (and starts on a few other components) --- .../Execution26/detail/almost_scheduler.hpp | 38 +++++++ .../Execution26/detail/completion_domain.hpp | 22 +++++ .../Execution26/detail/get_domain_late.hpp | 21 +++- .../Execution26/detail/get_scheduler.hpp | 5 + include/Beman/Execution26/detail/schedule.hpp | 44 +++++++++ .../Beman/Execution26/detail/scheduler.hpp | 38 +++++++ src/Beman/Execution26/tests/CMakeLists.txt | 2 + .../Execution26/tests/exec-sched.pass.cpp | 98 +++++++++++++++++++ .../Execution26/tests/exec-schedule.pass.cpp | 59 +++++++++++ 9 files changed, 324 insertions(+), 3 deletions(-) create mode 100644 include/Beman/Execution26/detail/almost_scheduler.hpp create mode 100644 include/Beman/Execution26/detail/completion_domain.hpp create mode 100644 include/Beman/Execution26/detail/schedule.hpp create mode 100644 include/Beman/Execution26/detail/scheduler.hpp create mode 100644 src/Beman/Execution26/tests/exec-sched.pass.cpp create mode 100644 src/Beman/Execution26/tests/exec-schedule.pass.cpp diff --git a/include/Beman/Execution26/detail/almost_scheduler.hpp b/include/Beman/Execution26/detail/almost_scheduler.hpp new file mode 100644 index 00000000..f1e96f2b --- /dev/null +++ b/include/Beman/Execution26/detail/almost_scheduler.hpp @@ -0,0 +1,38 @@ +// include/Beman/Execution26/detail/almost_scheduler.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_ALMOST_SCHEDULER +#define INCLUDED_BEMAN_EXECUTION26_DETAIL_ALMOST_SCHEDULER + +#include +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- + +namespace Beman::Execution26 +{ + struct scheduler_t {}; +} + +namespace Beman::Execution26::Detail +{ + template + concept almost_scheduler + = ::std::derived_from::scheduler_concept, + ::Beman::Execution26::scheduler_t> + && ::Beman::Execution26::Detail::queryable + && requires(Scheduler&& sched) { + { ::Beman::Execution26::schedule(::std::forward(sched)) } + -> ::Beman::Execution26::sender; + } + && ::std::equality_comparable<::std::remove_cvref_t> + && ::std::copy_constructible<::std::remove_cvref_t> + ; +} + +// ---------------------------------------------------------------------------- + +#endif diff --git a/include/Beman/Execution26/detail/completion_domain.hpp b/include/Beman/Execution26/detail/completion_domain.hpp new file mode 100644 index 00000000..eb8cce90 --- /dev/null +++ b/include/Beman/Execution26/detail/completion_domain.hpp @@ -0,0 +1,22 @@ +// include/Beman/Execution26/detail/completion_domain.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_COMPLETION_DOMAIN +#define INCLUDED_BEMAN_EXECUTION26_DETAIL_COMPLETION_DOMAIN + +#include + +// ---------------------------------------------------------------------------- + +namespace Beman::Execution26::Detail +{ + template + constexpr auto completion_domain(Sender const&) noexcept + { + //-dk:TODO + } +} + +// ---------------------------------------------------------------------------- + +#endif diff --git a/include/Beman/Execution26/detail/get_domain_late.hpp b/include/Beman/Execution26/detail/get_domain_late.hpp index 81130d37..83ca53b2 100644 --- a/include/Beman/Execution26/detail/get_domain_late.hpp +++ b/include/Beman/Execution26/detail/get_domain_late.hpp @@ -4,22 +4,37 @@ #ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_GET_DOMAIN_LATE #define INCLUDED_BEMAN_EXECUTION26_DETAIL_GET_DOMAIN_LATE -// #include #include +#include +#include +#include +#include #include +#include // ---------------------------------------------------------------------------- namespace Beman::Execution26::Detail { + template + concept not_void = not ::std::same_as; + template struct get_domain_late_helper { template static constexpr auto get(Sender const& sender, Env const& env) noexcept { - (void)sender; (void)env; - return ::Beman::Execution26::default_domain(); + if constexpr (requires{ { ::Beman::Execution26::get_domain(::Beman::Execution26::get_env(sender)) } -> ::Beman::Execution26::Detail::not_void; }) + return ::Beman::Execution26::get_domain(::Beman::Execution26::get_env(sender)); + else if constexpr (requires{ { ::Beman::Execution26::Detail::completion_domain(sender) } -> ::Beman::Execution26::Detail::not_void; }) + return ::Beman::Execution26::Detail::completion_domain(sender); + else if constexpr (requires{ { ::Beman::Execution26::get_domain(env) } -> ::Beman::Execution26::Detail::not_void; }) + return ::Beman::Execution26::get_domain(env); + else if constexpr (requires{ { ::Beman::Execution26::get_domain(::Beman::Execution26::get_scheduler(env)) } -> ::Beman::Execution26::Detail::not_void; }) + return ::Beman::Execution26::get_domain(::Beman::Execution26::get_scheduler(env)); + else + return ::Beman::Execution26::default_domain(); } }; template diff --git a/include/Beman/Execution26/detail/get_scheduler.hpp b/include/Beman/Execution26/detail/get_scheduler.hpp index 14b24242..c3ea51bb 100644 --- a/include/Beman/Execution26/detail/get_scheduler.hpp +++ b/include/Beman/Execution26/detail/get_scheduler.hpp @@ -15,6 +15,11 @@ namespace Beman::Execution26 : ::Beman::Execution26::forwarding_query_t { template + requires requires(get_scheduler_t const& self, Env&& env) + { + ::std::as_const(env).query(self); + + } auto operator()(Env&& env) const noexcept { static_assert(noexcept(::std::as_const(env).query(*this))); diff --git a/include/Beman/Execution26/detail/schedule.hpp b/include/Beman/Execution26/detail/schedule.hpp new file mode 100644 index 00000000..1b2c414c --- /dev/null +++ b/include/Beman/Execution26/detail/schedule.hpp @@ -0,0 +1,44 @@ +// include/Beman/Execution26/detail/schedule.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_SCHEDULE +#define INCLUDED_BEMAN_EXECUTION26_DETAIL_SCHEDULE + +#include +#include +#include + +// ---------------------------------------------------------------------------- + +namespace Beman::Execution26 +{ + struct schedule_t + { + template + requires (not requires(Scheduler&& sched) + { + { ::std::forward(sched).schedule() } + -> ::Beman::Execution26::sender; + }) + auto operator()(Scheduler&& sched) const + = BEMAN_EXECUTION26_DELETE("the scheduler needs a schedule() member returning a sender"); + + template + requires requires(Scheduler&& sched) + { + { ::std::forward(sched).schedule() } + -> ::Beman::Execution26::sender; + } + auto operator()(Scheduler&& sched) const + noexcept(noexcept(std::forward(sched).schedule())) + { + return std::forward(sched).schedule(); + } + }; + + inline constexpr ::Beman::Execution26::schedule_t schedule{}; +} + +// ---------------------------------------------------------------------------- + +#endif diff --git a/include/Beman/Execution26/detail/scheduler.hpp b/include/Beman/Execution26/detail/scheduler.hpp new file mode 100644 index 00000000..f7b3e61d --- /dev/null +++ b/include/Beman/Execution26/detail/scheduler.hpp @@ -0,0 +1,38 @@ +// include/Beman/Execution26/detail/scheduler.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_SCHEDULER +#define INCLUDED_BEMAN_EXECUTION26_DETAIL_SCHEDULER + +#include +#include +#include +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- + +namespace Beman::Execution26 +{ + template + concept scheduler + = ::Beman::Execution26::Detail::almost_scheduler + && requires(Scheduler&& sched) { + { + auto(::Beman::Execution26::get_completion_scheduler<::Beman::Execution26::set_value_t>( + ::Beman::Execution26::get_env( + ::Beman::Execution26::schedule( + ::std::forward(sched) + ) + ) + )) + } -> ::std::same_as<::std::remove_cvref_t>; + } + ; +} + +// ---------------------------------------------------------------------------- + +#endif diff --git a/src/Beman/Execution26/tests/CMakeLists.txt b/src/Beman/Execution26/tests/CMakeLists.txt index 3c3c2140..1a7998a9 100644 --- a/src/Beman/Execution26/tests/CMakeLists.txt +++ b/src/Beman/Execution26/tests/CMakeLists.txt @@ -2,6 +2,8 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception list(APPEND execution_tests + exec-sched.pass + exec-schedule.pass exec-domain-default.pass exec-get-scheduler.pass exec-get-compl-sched.pass diff --git a/src/Beman/Execution26/tests/exec-sched.pass.cpp b/src/Beman/Execution26/tests/exec-sched.pass.cpp new file mode 100644 index 00000000..9580e63a --- /dev/null +++ b/src/Beman/Execution26/tests/exec-sched.pass.cpp @@ -0,0 +1,98 @@ +// src/Beman/Execution26/tests/exec-sched.pass.cpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include + +// ---------------------------------------------------------------------------- + +namespace +{ + struct bad_env + { + auto query(test_std::get_completion_scheduler_t const&) const noexcept + { + return 0; + } + }; + + template + struct env + { + auto query(test_std::get_completion_scheduler_t const&) const noexcept + { + return Scheduler{}; + } + }; + + template + struct sender + { + using sender_concept = test_std::sender_t; + auto get_env() const noexcept { return Env{}; } + }; + + struct no_scheduler_concept + { + auto schedule() -> sender> { return {}; } + auto operator== (no_scheduler_concept const&) const -> bool = default; + }; + + struct not_queryable + { + using scheduler_concept = test_std::scheduler_t; + ~not_queryable() = delete; + auto schedule() -> sender> { return {}; } + auto operator== (not_queryable const&) const -> bool = default; + }; + + struct no_schedule + { + using scheduler_concept = test_std::scheduler_t; + auto operator== (no_schedule const&) const -> bool = default; + }; + + struct not_equality_comparable + { + using scheduler_concept = test_std::scheduler_t; + auto schedule() -> sender> { return {}; } + }; + + struct not_copy_constructible + { + using scheduler_concept = test_std::scheduler_t; + not_copy_constructible(not_copy_constructible const&) = delete; + auto schedule() -> sender> { return {}; } + auto operator== (not_copy_constructible const&) const -> bool = default; + }; + + struct scheduler + { + using scheduler_concept = test_std::scheduler_t; + auto schedule() -> sender> { return {}; } + auto operator== (scheduler const&) const -> bool = default; + }; + + struct bad_completion_scheduler + { + using scheduler_concept = test_std::scheduler_t; + auto schedule() -> sender> { return {}; } + auto operator== (bad_completion_scheduler const&) const -> bool = default; + }; +} + +auto main() -> int +{ + static_assert(test_std::sender>>); + static_assert(std::same_as, decltype(test_std::get_env(sender>{}))>); + static_assert(std::same_as(bad_env{}))>); + + static_assert(not test_std::scheduler); + static_assert(not test_std::scheduler); + static_assert(not test_std::scheduler); + static_assert(not test_std::scheduler); + static_assert(not test_std::scheduler); + static_assert(not test_std::scheduler); + static_assert(not test_std::scheduler); + static_assert(test_std::scheduler); +} \ No newline at end of file diff --git a/src/Beman/Execution26/tests/exec-schedule.pass.cpp b/src/Beman/Execution26/tests/exec-schedule.pass.cpp new file mode 100644 index 00000000..ad700774 --- /dev/null +++ b/src/Beman/Execution26/tests/exec-schedule.pass.cpp @@ -0,0 +1,59 @@ +// src/Beman/Execution26/tests/exec-schedule.pass.cpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- + +namespace +{ + struct non_scheduler + { + }; + + struct sender + { + using sender_concept = test_std::sender_t; + int value{}; + auto operator== (sender const&) const -> bool = default; + }; + + template + struct scheduler + { + int value{}; + auto schedule() noexcept(Noexcept) { return Sender{this->value}; } + }; + + struct rvalue_scheduler + { + int value{}; + auto schedule() && noexcept { return sender{this->value}; } + }; + + template + auto test_schedule(Scheduler&& sched) + { + static_assert(Expect == requires{ test_std::schedule(::std::forward(sched)); }); + if constexpr (Expect) + { + static_assert(noexcept(test_std::schedule(std::forward(sched))) == noexcept(std::forward(sched).schedule())); + auto s = test_std::schedule(std::forward(sched)); + assert(s.value == sched.value); + } + } +} + +auto main() -> int +{ + static_assert(std::same_as); + static_assert(test_std::sender); + test_schedule(non_scheduler{}); + test_schedule(scheduler{17}); + test_schedule(scheduler{17}); + test_schedule(scheduler{17}); + test_schedule(rvalue_scheduler{17}); +} \ No newline at end of file From fc227dc53abf46774d60d43c410a6c5c86caa11d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Mon, 19 Aug 2024 22:37:13 +0100 Subject: [PATCH 08/29] changed code to make g++ more happy --- include/Beman/Execution26/detail/scheduler.hpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/include/Beman/Execution26/detail/scheduler.hpp b/include/Beman/Execution26/detail/scheduler.hpp index f7b3e61d..fac00541 100644 --- a/include/Beman/Execution26/detail/scheduler.hpp +++ b/include/Beman/Execution26/detail/scheduler.hpp @@ -14,6 +14,13 @@ // ---------------------------------------------------------------------------- +namespace Beman::Execution26::Detail +{ + template + concept decayed_same_as + = ::std::same_as<::std::remove_cvref_t, ::std::remove_cvref_t> + ; +} namespace Beman::Execution26 { template @@ -21,14 +28,14 @@ namespace Beman::Execution26 = ::Beman::Execution26::Detail::almost_scheduler && requires(Scheduler&& sched) { { - auto(::Beman::Execution26::get_completion_scheduler<::Beman::Execution26::set_value_t>( + ::Beman::Execution26::get_completion_scheduler<::Beman::Execution26::set_value_t>( ::Beman::Execution26::get_env( ::Beman::Execution26::schedule( ::std::forward(sched) ) ) - )) - } -> ::std::same_as<::std::remove_cvref_t>; + ) + } -> ::Beman::Execution26::Detail::decayed_same_as; } ; } From 9c9ab7ed0317e63657e12584ff3d9bbc49299885 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Tue, 20 Aug 2024 23:22:00 +0100 Subject: [PATCH 09/29] completed get_completion_scheduler to test for scheduler while not depending on it --- docs/questions.md | 2 + .../Beman/Execution26/detail/continues_on.hpp | 1 + .../Execution26/detail/decayed_same_as.hpp | 22 +++++++ .../detail/get_completion_scheduler.hpp | 57 +++++++++++++++++-- .../detail/get_completion_signatures.hpp | 9 ++- .../Beman/Execution26/detail/scheduler.hpp | 8 +-- .../Beman/Execution26/detail/sender_in.hpp | 34 +++++++++++ .../tests/exec-get-compl-sched.pass.cpp | 33 +++++++++-- .../Execution26/tests/exec-sched.pass.cpp | 44 ++++++++++---- .../tests/exec-snd-concepts.pass.cpp | 19 +++++++ 10 files changed, 201 insertions(+), 28 deletions(-) create mode 100644 include/Beman/Execution26/detail/decayed_same_as.hpp create mode 100644 include/Beman/Execution26/detail/sender_in.hpp diff --git a/docs/questions.md b/docs/questions.md index f6cd256e..386cc19b 100644 --- a/docs/questions.md +++ b/docs/questions.md @@ -18,3 +18,5 @@ likely observable. - [exec.snd.expos] uses query-or-default; it seems only query-with-default is defined. - [exec.snd.concepts] "The type tag_of_t is +defined+ as follows:" +- [exec.sched] uses `auto(get_completion_scheduler(...))` + which is OK for clang but doesn't seem to compile for g++ os MSVC. \ No newline at end of file diff --git a/include/Beman/Execution26/detail/continues_on.hpp b/include/Beman/Execution26/detail/continues_on.hpp index 6a8fe60d..d6f9937b 100644 --- a/include/Beman/Execution26/detail/continues_on.hpp +++ b/include/Beman/Execution26/detail/continues_on.hpp @@ -8,6 +8,7 @@ namespace Beman::Execution26 { + // specialize default_domain appropriately struct continues_on_t { //-dk:TODO provide actual implementation diff --git a/include/Beman/Execution26/detail/decayed_same_as.hpp b/include/Beman/Execution26/detail/decayed_same_as.hpp new file mode 100644 index 00000000..9df6ce23 --- /dev/null +++ b/include/Beman/Execution26/detail/decayed_same_as.hpp @@ -0,0 +1,22 @@ +// include/Beman/Execution26/detail/decayed_same_as.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_DECAYED_SAME_AS +#define INCLUDED_BEMAN_EXECUTION26_DETAIL_DECAYED_SAME_AS + +#include + +// ---------------------------------------------------------------------------- + +namespace Beman::Execution26::Detail +{ + //-dk:TODO thoroughly test the concept + template + concept decayed_same_as + = ::std::same_as<::std::remove_cvref_t, ::std::remove_cvref_t> + ; +} + +// ---------------------------------------------------------------------------- + +#endif diff --git a/include/Beman/Execution26/detail/get_completion_scheduler.hpp b/include/Beman/Execution26/detail/get_completion_scheduler.hpp index 17113ecb..89f7f37f 100644 --- a/include/Beman/Execution26/detail/get_completion_scheduler.hpp +++ b/include/Beman/Execution26/detail/get_completion_scheduler.hpp @@ -4,10 +4,15 @@ #ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_GET_COMPLETION_SCHEDULER #define INCLUDED_BEMAN_EXECUTION26_DETAIL_GET_COMPLETION_SCHEDULER +#include +#include #include +#include +#include #include #include #include +#include #include #include #include @@ -16,18 +21,60 @@ namespace Beman::Execution26 { + template + struct get_completion_scheduler_t; + template struct get_completion_scheduler_t : ::Beman::Execution26::forwarding_query_t { template + requires (not requires(get_completion_scheduler_t const& self, + ::std::remove_cvref_t const& env) { + env.query(self); + }) + auto operator()(Env&&) const noexcept + = BEMAN_EXECUTION26_DELETE("The environment needs a query(get_completion_scheduler_t) member"); + + template + requires (not requires(get_completion_scheduler_t const& self, + ::std::remove_cvref_t const& env) { + { env.query(self) } noexcept; + }) + auto operator()(Env&&) const noexcept + = BEMAN_EXECUTION26_DELETE("The environment's query(get_completion_scheduler_t) has to be noexcept"); + + template + requires (not requires(get_completion_scheduler_t const& self, + get_completion_scheduler_t<::Beman::Execution26::set_value_t> const& value_self, + ::std::remove_cvref_t const& env) { + { + env.query(self) + } noexcept -> ::Beman::Execution26::Detail::almost_scheduler; + { + ::Beman::Execution26::get_env( + ::Beman::Execution26::schedule(env.query(self)) + ).query(value_self) + } -> ::Beman::Execution26::Detail::decayed_same_as; + }) + auto operator()(Env&&) const noexcept + = BEMAN_EXECUTION26_DELETE("The environment's query(get_completion_scheduler_t) has to return a scheduler"); + + template + requires requires(get_completion_scheduler_t const& self, + get_completion_scheduler_t<::Beman::Execution26::set_value_t> const& value_self, + ::std::remove_cvref_t const& env) { + { + env.query(self) + } noexcept -> ::Beman::Execution26::Detail::almost_scheduler; + { + ::Beman::Execution26::get_env( + ::Beman::Execution26::schedule(env.query(self)) + ).query(value_self) + } -> ::Beman::Execution26::Detail::decayed_same_as; + } auto operator()(Env&& env) const noexcept { - static_assert(noexcept(::std::as_const(env).query(*this))); - //-dk:TODO mandate result is a scheduler: - // static_assert(::Beman::Execution26::scheduler< - // decltype(::std::as_const(env).query(*this)) - // >); return ::std::as_const(env).query(*this); } }; diff --git a/include/Beman/Execution26/detail/get_completion_signatures.hpp b/include/Beman/Execution26/detail/get_completion_signatures.hpp index d3ad8879..ea6126d5 100644 --- a/include/Beman/Execution26/detail/get_completion_signatures.hpp +++ b/include/Beman/Execution26/detail/get_completion_signatures.hpp @@ -4,13 +4,20 @@ #ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_GET_COMPLETION_SIGNATURES #define INCLUDED_BEMAN_EXECUTION26_DETAIL_GET_COMPLETION_SIGNATURES +#include //-dk:TODO remove + // ---------------------------------------------------------------------------- namespace Beman::Execution26 { struct get_completion_signatures_t { - //-dk:TODO add implementation + template + auto operator()(Sender&&, Env&&) const noexcept + { + return ::Beman::Execution26::completion_signatures<>{}; + //-dk:TODO implement! + } }; inline constexpr get_completion_signatures_t get_completion_signatures{}; } diff --git a/include/Beman/Execution26/detail/scheduler.hpp b/include/Beman/Execution26/detail/scheduler.hpp index fac00541..d4e1e29f 100644 --- a/include/Beman/Execution26/detail/scheduler.hpp +++ b/include/Beman/Execution26/detail/scheduler.hpp @@ -5,6 +5,7 @@ #define INCLUDED_BEMAN_EXECUTION26_DETAIL_SCHEDULER #include +#include #include #include #include @@ -14,13 +15,6 @@ // ---------------------------------------------------------------------------- -namespace Beman::Execution26::Detail -{ - template - concept decayed_same_as - = ::std::same_as<::std::remove_cvref_t, ::std::remove_cvref_t> - ; -} namespace Beman::Execution26 { template diff --git a/include/Beman/Execution26/detail/sender_in.hpp b/include/Beman/Execution26/detail/sender_in.hpp new file mode 100644 index 00000000..6828f084 --- /dev/null +++ b/include/Beman/Execution26/detail/sender_in.hpp @@ -0,0 +1,34 @@ +// include/Beman/Execution26/detail/sender_in.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_SENDER_IN +#define INCLUDED_BEMAN_EXECUTION26_DETAIL_SENDER_IN + +#include +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- + +namespace Beman::Execution26 +{ + template + concept sender_in + = ::Beman::Execution26::sender + && ::Beman::Execution26::Detail::queryable + && requires(Sender&& sender, Env&& env) { + { + ::Beman::Execution26::get_completion_signatures( + ::std::forward(sender), + ::std::forward(env) + ) + } -> ::Beman::Execution26::Detail::valid_completion_signatures; + } + ; +} + +// ---------------------------------------------------------------------------- + +#endif diff --git a/src/Beman/Execution26/tests/exec-get-compl-sched.pass.cpp b/src/Beman/Execution26/tests/exec-get-compl-sched.pass.cpp index db8d2eff..76d13928 100644 --- a/src/Beman/Execution26/tests/exec-get-compl-sched.pass.cpp +++ b/src/Beman/Execution26/tests/exec-get-compl-sched.pass.cpp @@ -3,6 +3,9 @@ #include #include +#include +#include +#include #include #include #include @@ -15,19 +18,32 @@ namespace { struct tag {}; + template struct env; + + template + struct sender + { + using sender_concept = test_std::sender_t; + auto get_env() const noexcept -> env { return {}; } + + }; + template struct scheduler { + using scheduler_concept = test_std::scheduler_t; int value{}; auto operator== (scheduler const&) const -> bool = default; + auto schedule() noexcept -> sender { return {}; } }; + template struct env { int value{}; auto query(test_std::get_completion_scheduler_t const&) const noexcept { - return scheduler{this->value + 1}; + return scheduler{this->value + 1}; } auto query(test_std::get_completion_scheduler_t const&) const noexcept { @@ -37,10 +53,10 @@ namespace { return scheduler{this->value + 3}; } - template - auto query(test_std::get_completion_scheduler_t const&) const noexcept + template + auto query(test_std::get_completion_scheduler_t const&) const noexcept { - return scheduler{this->value}; + return scheduler{this->value}; } }; @@ -53,6 +69,13 @@ namespace auto main() -> int { + static_assert(test_std::sender>); + static_assert(test_std::sender>); + static_assert(test_std::sender>); + static_assert(test_std::scheduler>); + static_assert(test_std::scheduler>); + static_assert(test_std::scheduler>); + static_assert(std::same_as const, decltype(test_std::get_completion_scheduler)>); static_assert(std::same_as const, @@ -63,7 +86,7 @@ auto main() -> int static_assert(test_std::forwarding_query(test_std::get_completion_scheduler)); static_assert(test_std::forwarding_query(test_std::get_completion_scheduler)); - env e{17}; + env e{17}; test_tag(e); test_tag(e); test_tag(e); diff --git a/src/Beman/Execution26/tests/exec-sched.pass.cpp b/src/Beman/Execution26/tests/exec-sched.pass.cpp index 9580e63a..78f77528 100644 --- a/src/Beman/Execution26/tests/exec-sched.pass.cpp +++ b/src/Beman/Execution26/tests/exec-sched.pass.cpp @@ -79,20 +79,44 @@ namespace auto schedule() -> sender> { return {}; } auto operator== (bad_completion_scheduler const&) const -> bool = default; }; + + template + auto test_get_completion_scheduler(Result&& result, Env&& env) ->void + { + static_assert(Expect == requires{ + test_std::get_completion_scheduler(env); + }); + if constexpr (Expect) + { + static_assert(::std::same_as< + std::remove_cvref_t, + std::remove_cvref_t(env))> + > + ); + assert(result == test_std::get_completion_scheduler(env)); + } + } + + template + auto test_scheduler() -> void + { + static_assert(Expect == test_std::scheduler); + } } auto main() -> int { static_assert(test_std::sender>>); static_assert(std::same_as, decltype(test_std::get_env(sender>{}))>); - static_assert(std::same_as(bad_env{}))>); - - static_assert(not test_std::scheduler); - static_assert(not test_std::scheduler); - static_assert(not test_std::scheduler); - static_assert(not test_std::scheduler); - static_assert(not test_std::scheduler); - static_assert(not test_std::scheduler); - static_assert(not test_std::scheduler); - static_assert(test_std::scheduler); + + test_get_completion_scheduler(0, bad_env{}); + + test_scheduler(); + test_scheduler(); + test_scheduler(); + test_scheduler(); + test_scheduler(); + test_scheduler(); + test_scheduler(); + test_scheduler(); } \ No newline at end of file diff --git a/src/Beman/Execution26/tests/exec-snd-concepts.pass.cpp b/src/Beman/Execution26/tests/exec-snd-concepts.pass.cpp index 73044789..2d0f43eb 100644 --- a/src/Beman/Execution26/tests/exec-snd-concepts.pass.cpp +++ b/src/Beman/Execution26/tests/exec-snd-concepts.pass.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -105,6 +106,23 @@ namespace static_assert(test_std::sender); } + auto test_sender_in() -> void + { + struct non_queryable { ~non_queryable() = delete; }; + struct queryable {}; + struct non_sender_in {}; + struct sender_in + { + using sender_concept = test_std::sender_t; + }; + + static_assert(not test_std::sender_in); + static_assert(not test_std::sender_in); + static_assert(test_std::sender_in); + static_assert(test_std::sender_in); + //-dk:TODO add missing test cases + } + auto test_tag_of_t() -> void { //auto&& [tag, data, ...children] = tagged_sender(); @@ -133,6 +151,7 @@ auto main() -> int test_is_sender(); test_enable_sender(); test_sender(); + test_sender_in(); test_tag_of_t(); test_sender_for(); } \ No newline at end of file From 50bfd64f6a2bb3da3e1945eba107295f4401fc75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Wed, 21 Aug 2024 23:31:04 +0100 Subject: [PATCH 10/29] added completion_domain implementation --- Makefile | 12 ++- .../Execution26/detail/completion_domain.hpp | 68 ++++++++++++- .../detail/get_completion_scheduler.hpp | 20 +++- .../Execution26/tests/exec-snd-expos.pass.cpp | 97 +++++++++++++++++++ 4 files changed, 190 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 4cf26d85..052c16f0 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception SANITIZERS = none msan asan usan tsan -.PHONY: default todo ce distclean clean build test all $(SANITIZERS) +.PHONY: default check ce todo distclean clean build test all $(SANITIZERS) CXX_FLAGS = -g SANITIZER = none @@ -53,9 +53,19 @@ build: test: build cd $(BUILD); $(MAKE) test +<<<<<<< HEAD ce: @mkdir -p $(BUILD) bin/mk-compiler-explorer.py $(BUILD) +======= +check: + @for h in `find include -name \*.hpp`; \ + do \ + from=`echo -n $$h | sed -n 's@.*Beman/\(.*\).hpp.*@\1@p'`; \ + < $$h sed -n "/^ *# *include .*@$$from \1@p"; \ + done | tsort > /dev/null + +>>>>>>> 3ed6667 (added completion_domain implementation) todo: bin/mk-todo.py diff --git a/include/Beman/Execution26/detail/completion_domain.hpp b/include/Beman/Execution26/detail/completion_domain.hpp index eb8cce90..f85773e1 100644 --- a/include/Beman/Execution26/detail/completion_domain.hpp +++ b/include/Beman/Execution26/detail/completion_domain.hpp @@ -5,15 +5,79 @@ #define INCLUDED_BEMAN_EXECUTION26_DETAIL_COMPLETION_DOMAIN #include +#include +#include +#include +#include +#include // ---------------------------------------------------------------------------- namespace Beman::Execution26::Detail { + struct completion_domain_undefined {}; + template + struct completion_domain_merge + { + }; + template + struct completion_domain_merge + { + using type = T; + }; + template + struct completion_domain_merge + { + using type = T; + }; + template + struct completion_domain_merge + { + using type = T; + }; + template <> + struct completion_domain_merge + { + using type = completion_domain_undefined; + }; + template - constexpr auto completion_domain(Sender const&) noexcept + constexpr auto completion_domain(Sender const& sender) noexcept { - //-dk:TODO + + static_assert(::Beman::Execution26::sender); + auto get = [&sender](Tag) { + if constexpr (requires{ + ::Beman::Execution26::get_domain( + ::Beman::Execution26::get_completion_scheduler( + ::Beman::Execution26::get_env(sender) + ) + ); + }) + { + return ::Beman::Execution26::get_domain( + ::Beman::Execution26::get_completion_scheduler( + ::Beman::Execution26::get_env(sender) + ) + ); + } + else + { + return completion_domain_undefined{}; + } + }; + + using type = typename completion_domain_merge< + typename completion_domain_merge< + decltype(get(::Beman::Execution26::set_error)), + decltype(get(::Beman::Execution26::set_stopped)) + >::type, + decltype(get(::Beman::Execution26::set_value)) + >::type; + return ::std::conditional_t< + ::std::same_as, + Default, + type>(); } } diff --git a/include/Beman/Execution26/detail/get_completion_scheduler.hpp b/include/Beman/Execution26/detail/get_completion_scheduler.hpp index 89f7f37f..61ab6f18 100644 --- a/include/Beman/Execution26/detail/get_completion_scheduler.hpp +++ b/include/Beman/Execution26/detail/get_completion_scheduler.hpp @@ -37,15 +37,27 @@ namespace Beman::Execution26 = BEMAN_EXECUTION26_DELETE("The environment needs a query(get_completion_scheduler_t) member"); template - requires (not requires(get_completion_scheduler_t const& self, + requires (requires(get_completion_scheduler_t const& self, + ::std::remove_cvref_t const& env) { + env.query(self); + } + && (not requires(get_completion_scheduler_t const& self, ::std::remove_cvref_t const& env) { { env.query(self) } noexcept; - }) + })) auto operator()(Env&&) const noexcept = BEMAN_EXECUTION26_DELETE("The environment's query(get_completion_scheduler_t) has to be noexcept"); template - requires (not requires(get_completion_scheduler_t const& self, + requires (requires(get_completion_scheduler_t const& self, + ::std::remove_cvref_t const& env) { + env.query(self); + } + && requires(get_completion_scheduler_t const& self, + ::std::remove_cvref_t const& env) { + { env.query(self) } noexcept; + } + && (not requires(get_completion_scheduler_t const& self, get_completion_scheduler_t<::Beman::Execution26::set_value_t> const& value_self, ::std::remove_cvref_t const& env) { { @@ -56,7 +68,7 @@ namespace Beman::Execution26 ::Beman::Execution26::schedule(env.query(self)) ).query(value_self) } -> ::Beman::Execution26::Detail::decayed_same_as; - }) + })) auto operator()(Env&&) const noexcept = BEMAN_EXECUTION26_DELETE("The environment's query(get_completion_scheduler_t) has to return a scheduler"); diff --git a/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp b/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp index 9574489d..6da0c2b7 100644 --- a/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp +++ b/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp @@ -198,6 +198,99 @@ namespace assert(dom == domain{17}); } + namespace completion_domain { + struct domain {}; + struct other {}; + struct common {}; + struct none {}; + struct mismatch {}; + + template struct env; + template struct scheduler; + + template + struct sender + { + using sender_concept = test_std::sender_t; + auto get_env() const noexcept -> env { return {}; } + }; + template + struct scheduler + { + using scheduler_concept = test_std::scheduler_t; + auto schedule() noexcept -> sender { return {}; } + auto operator== (scheduler const&) const -> bool = default; + auto query(test_std::get_domain_t const&) const noexcept -> domain { return {}; } + }; + + template <> + struct scheduler + { + using scheduler_concept = test_std::scheduler_t; + auto schedule() noexcept -> sender { return {}; } + auto operator== (scheduler const&) const -> bool = default; + }; + + template <> + struct env + { + template + auto query(test_std::get_completion_scheduler_t const&) const noexcept + -> scheduler + { + return {}; + } + }; + + template <> + struct env + { + template + auto query(test_std::get_completion_scheduler_t const&) const noexcept + -> scheduler + { + return {}; + } + }; + + struct one_missing {}; + template <> + struct env + { + template + auto query(test_std::get_completion_scheduler_t const&) const noexcept + -> scheduler + { + return {}; + } + auto query(test_std::get_completion_scheduler_t const&) const noexcept = delete; + }; + + struct two_missing {}; + template <> + struct env + { + auto query(test_std::get_completion_scheduler_t const&) const noexcept + -> scheduler + { + return {}; + } + }; + } + auto test_completion_domain() -> void + { + namespace cd = completion_domain; + static_assert(test_std::sender>); + static_assert(std::same_as, decltype(test_std::get_env(cd::sender{}))>); + static_assert(std::same_as(cd::env{})))>); + static_assert(std::same_as(cd::env{})))>); + static_assert(std::same_as(cd::env{})))>); + static_assert(std::same_as{})))>); + static_assert(std::same_as{})))>); + static_assert(std::same_as{})))>); + static_assert(std::same_as{})))>); + } + auto test_query_with_default() -> void { auto result1{test_detail::query_with_default(test_std::get_domain, @@ -215,11 +308,14 @@ namespace auto test_get_domain_late() -> void { + #if 0 static_assert(test_std::sender); env const e; test_sender const sndr; auto dom{test_detail::get_domain_late(sndr, e)}; (void)dom; + //-dk:TOO test + #endif } } @@ -230,6 +326,7 @@ auto main() -> int test_join_env(); test_sched_attrs(); test_sched_env(); + test_completion_domain(); test_query_with_default(); test_get_domain_late(); } \ No newline at end of file From 4f3c973d99b09300541c16002a5bee7741073f4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Thu, 22 Aug 2024 22:46:53 +0100 Subject: [PATCH 11/29] fixed a leftover merge conflict --- Makefile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 052c16f0..00f12c73 100644 --- a/Makefile +++ b/Makefile @@ -53,11 +53,10 @@ build: test: build cd $(BUILD); $(MAKE) test -<<<<<<< HEAD ce: @mkdir -p $(BUILD) bin/mk-compiler-explorer.py $(BUILD) -======= + check: @for h in `find include -name \*.hpp`; \ do \ @@ -65,7 +64,6 @@ check: < $$h sed -n "/^ *# *include .*@$$from \1@p"; \ done | tsort > /dev/null ->>>>>>> 3ed6667 (added completion_domain implementation) todo: bin/mk-todo.py From d90c6d8c9bafe196a6ed996faf40b4b12427810e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Sun, 25 Aug 2024 00:39:13 +0100 Subject: [PATCH 12/29] added a file with component dependencies --- docs/dependency.txt | 507 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 507 insertions(+) create mode 100644 docs/dependency.txt diff --git a/docs/dependency.txt b/docs/dependency.txt new file mode 100644 index 00000000..681f0315 --- /dev/null +++ b/docs/dependency.txt @@ -0,0 +1,507 @@ +apply_sender is_sender +as_awaitable is_awaitable +await_result_type get_awaiter +awaitable_receiver forwarding_query +awaitable_receiver get_env +awaitable_receiver receiver_t +awaitable_receiver set_error +awaitable_receiver set_stopped +awaitable_receiver set_value +awaitable_sender awaitable_receiver +awaitable_sender env_of_t +awaitable_sender single_sender +basic_operation basic_state +basic_operation connect_all_result +basic_operation impls_for +basic_operation indices_for +basic_operation inner_ops +basic_operation operation_state_t +basic_operation state_type +basic_operation tag_of_t +basic_operation valid_specialization +basic_receiver basic_state +basic_receiver callable +basic_receiver complete +basic_receiver impls_for +basic_receiver receiver_t +basic_receiver set_error +basic_receiver set_stopped +basic_receiver set_value +basic_receiver state_type +basic_receiver tag_of_t +basic_receiver valid_specialization +basic_sender basic_operation +basic_sender impls_for +basic_sender product_type +basic_sender sender_t +basic_state impls_for +basic_state state_type +basic_state tag_of_t +bulk default_impls +bulk get_domain_early +bulk impls_for +bulk make_sender +bulk movable_value +bulk product_type +bulk sender +bulk sender_adaptor_closure +bulk try_eval +completion_domain get_completion_scheduler +completion_domain get_domain +completion_domain get_env +completion_signature completion_signatures +completion_signature set_error +completion_signature set_stopped +completion_signature set_value +completion_signatures_for completion_signatures +completion_tag set_error +completion_tag set_set_stopped +completion_tag set_value +connect env_of_t +connect get_domain_late +connect get_env +connect operation_state_task +connect receiver +connect sender +connect transform_sender +connect with_await_transform +connect with_connect_awaitable_promise +connect_all basic_receiver +connect_all basic_state +connect_all product_type +connect_all_result basic_state +connect_all_result call_result +connect_all_result connect_all +connect_all_result indices_for +continues_on default_impls +continues_on fwd_env +continues_on get_domain_early +continues_on get_env +continues_on impls_for +continues_on join_env +continues_on make_sender +continues_on sched_attrs +continues_on schedule_from +continues_on scheduler +continues_on sender +continues_on sender_adaptor_closure +continues_on sender_for +default_domain queryable +default_domain sender +default_domain tag_of_t +default_set_error completion_signatures +default_set_error set_value +default_set_value completion_signatures +default_set_value set_value +emplace_from call_result_t +enable_sender empty_env +enable_sender env_promise +enable_sender is_awaitable +enable_sender is_sender +env_promise env_promise +env_promise with_await_transform +env_type call_result_t +env_type impls_for +env_type state_t +env_type tag_of_t +error_types_of_t gather_signatures +error_types_of_t set_error +fwd_env queryable +get_allocator mandate_nothrow +get_completion_schedulder completion_tag +get_completion_schedulder forwarding_query +get_completion_schedulder mandate_nothrow +get_completion_schedulder scheduler-break +get_completion_schedulder sender +get_completion_signatures await_result_type +get_completion_signatures completion_signatures +get_completion_signatures env_promise +get_completion_signatures get_domain_late +get_completion_signatures is_awaitable +get_completion_signatures set_error +get_completion_signatures set_stopped +get_completion_signatures transform_sender +get_delegation_scheduler forwarding_query +get_delegation_scheduler mandate_nothrow +get_delegation_scheduler scheduler +get_domain forwarding_query +get_domain mandate_nothrow +get_domain_early completion_domain +get_domain_early default_domain +get_domain_early get_domain +get_domain_early get_env +get_domain_late completion_domain +get_domain_late continues_on_t +get_domain_late default_domain +get_domain_late get_domain +get_domain_late get_scheduler +get_domain_late query_or_default +get_domain_late sender_for +get_env empty_env +get_env mandate_nothrow +get_env queryable +get_forward_progress_guarantee forward_progress_guarantee +get_forward_progress_guarantee mandate_nothrow +get_scheduler forwarding_query +get_scheduler mandate_nothrow +get_stop_token mandate_nothrow +get_stop_token never_stop_token +get_stop_token stoppable_token +has_as_awaitable is_awaitable +has_completions completion_signatures +has_completions valid_completions_for +impls_for default_impls +impls_for write_env-break +into_variant child_type +into_variant decayed_tuple +into_variant default_impls +into_variant env_of_t +into_variant get_domain_early +into_variant make_sender +into_variant sender +into_variant set_value +into_variant transform_sender +into_variant try_set_value +into_variant value_types_of_t +is_awaitable get_awaiter +is_awaitable is_awaiter +is_awaiter await_suspend_result +is_sender sender_t +join_env queryable +just decayed_typeof +just default_impls +just impls_for +just set_value +just_error decayed_typeof +just_error default_impls +just_error impls_for +just_error set_error +just_stopped decayed_typeof +just_stopped default_impls +just_stopped impls_for +just_stopped set_stopped +let_error as_tuple +let_error completion_signatures_of_t +let_error connect_result_t +let_error decayed_tuple +let_error decayed_typeof +let_error default_impls +let_error empty_env +let_error fwd_env +let_error get_completion_scheduler +let_error get_domain +let_error get_domain_early +let_error get_env +let_error impls_for +let_error join_env +let_error make_env +let_error make_sender +let_error movable_value +let_error receiver_t +let_error sched_env +let_error sender_adaptor_closure +let_error sender_for +let_error set_error +let_error set_stopped +let_error set_value +let_error transform_sender +let_error try_eval +let_stopped as_tuple +let_stopped completion_signatures_of_t +let_stopped connect_result_t +let_stopped decayed_tuple +let_stopped decayed_typeof +let_stopped default_impls +let_stopped empty_env +let_stopped fwd_env +let_stopped get_completion_scheduler +let_stopped get_domain +let_stopped get_domain_early +let_stopped get_env +let_stopped impls_for +let_stopped join_env +let_stopped make_env +let_stopped make_sender +let_stopped movable_value +let_stopped receiver_t +let_stopped sched_env +let_stopped sender_adaptor_closure +let_stopped sender_for +let_stopped set_error +let_stopped set_stopped +let_stopped set_value +let_stopped transform_sender +let_stopped try_eval +let_value as_tuple +let_value completion_signatures_of_t +let_value connect_result_t +let_value decayed_tuple +let_value decayed_typeof +let_value default_impls +let_value empty_env +let_value fwd_env +let_value get_completion_scheduler +let_value get_domain +let_value get_domain_early +let_value get_env +let_value impls_for +let_value join_env +let_value make_env +let_value make_sender +let_value movable_value +let_value receiver_t +let_value sched_env +let_value sender_adaptor_closure +let_value sender_for +let_value set_error +let_value set_stopped +let_value set_value +let_value transform_sender +let_value try_eval +make_env queryable +make_sender basic_sender +mandate_nothrow forwarding_query_t +on default_domain +on get_completion_scheduler +on get_domain +on get_env +on get_scheduler +on make_sender +on query_or_default +on sched_env +on scheduler +on sender +on sender_adaptor_closure +on sender_for +on sender_in +on sender_t +on set_value +on transform_sender +on write_env +on_stop_request inplace_stop_source +operation_state operation_state_t +operation_state start +operation_state_task connect_awaitable_promise +operation_state_task operation_state_t +read_env decayed_typeof +read_env default_impls +read_env get_env +read_env impls_for +read_env make_sender +read_env query +read_env try_set_value +receiver get_env +receiver queryable +receiver receiver_t +receiver_of has_completions +run_loop connect +run_loop get_completion_scheduler +run_loop get_env +run_loop get_stop_token +run_loop receiver_of +run_loop schedule +run_loop scheduler +run_loop sender +run_loop set_error +run_loop set_stopped +run_loop set_value +sched_attrs get_completion_schedulder +sched_attrs queryable +sched_env get_domain +sched_env get_scheduler +sched_env queryable +schedule sender +schedule_from as_tuple +schedule_from child_type +schedule_from completion_signatures_of_t +schedule_from connect +schedule_from connect_result_t +schedule_from default_domain +schedule_from default_impls +schedule_from env_of_t +schedule_from fwd_env +schedule_from get_domain +schedule_from get_env +schedule_from impls_for +schedule_from join_env +schedule_from make_sender +schedule_from op_state +schedule_from query_or_default +schedule_from receiver_t +schedule_from sched_attrs +schedule_from sched_t +schedule_from schedule +schedule_from schedule_result_t +schedule_from scheduler +schedule_from sender +schedule_from sender_in +schedule_from transform_sender +scheduler get_completion_schedulder +scheduler get_domain +scheduler get_env +scheduler queryable +scheduler schedule +scheduler schedule_result_t +scheduler scheduler_t +scheduler sender_in +scheduler set_value_t +sender enable_sender +sender get_env +sender queryable +sender_awaitable awaitable_receiver +sender_awaitable connect +sender_awaitable single_sender_value_type +sender_awaitable start +sender_in get_completion_signatures +sender_in queryable +sender_in sender +sender_in valid_completion_signatures +sender_in_of matching_sig +sender_in_of sender_in +sender_in_of set_value +sender_in_of value_signature +sender_in_of value_types_of_t +sender_of empty_env +sender_of sender_in_of +sender_of tag_of_t +sender_to completion_signatures_of_t +sender_to connect +sender_to env_of_t +sends_stopped completion_signatures_of_t +sends_stopped gather_signatures +sends_stopped set_stopped +set_error mandate_nothrow +set_stopped mandate_nothrow +set_value mandate_nothrow +set_value_sig set_value +single_sender sender_in +single_sender single_sender_value_type +single_sender_value_type decayed_tuple +single_sender_value_type value_types_of_t +split decayed_tuple +split env_of_t +split get_domain_early +split get_stop_token +split implace_stop_token +split make_sender +split receiver_t +split sender_in +split set_error +split set_stopped +split set_value +split stop_callback_of_t +split stop_token_of_t +split transform_sender +start mandate_nothrow +starts_on default_domain +starts_on fwd_env +starts_on get_domain +starts_on join_env +starts_on let_value +starts_on make_sender +starts_on query_or_default +starts_on sched_env +starts_on schedule +starts_on scheduler +starts_on sender +starts_on transform_sender +state_type call_result_t +state_type impls_for +state_type tag_of_t +stopped_as_error get_domain_early +stopped_as_error just_error +stopped_as_error let_stopped +stopped_as_error make_sender +stopped_as_error movable_value +stopped_as_error sender +stopped_as_error sender_for +stopped_as_error transform_sender +stopped_as_optional get_domain_early +stopped_as_optional just +stopped_as_optional let_stopped +stopped_as_optional make_sender +stopped_as_optional single_sender_value_type +stopped_as_optional then +stopped_as_optional transform_sender +sync_wait apply_sender +sync_wait callable +sync_wait connect +sync_wait decayed_tuple +sync_wait get_delegation_scheduler +sync_wait get_domain_early +sync_wait get_scheduler +sync_wait into_variant +sync_wait receiver_t +sync_wait run_loop +sync_wait sender_in +sync_wait sender_to +sync_wait start +sync_wait value_types_of_t +then decayed_typeof +then default_impls +then impls_for +then movable_value +then sender +then sender_adaptor_closure +then set_value +then try_set_value +transform_completion_signatures completion_signatures +transform_completion_signatures default_set_error +transform_completion_signatures default_set_value +transform_completion_signatures gather_signatures +transform_completion_signatures set_error +transform_completion_signatures set_stopped +transform_completion_signatures set_value +transform_completion_signatures valid_completion_signatures +transform_env default_domain +transform_env queryable +transform_env sender +transform_sender queryable +transform_sender sender +upon_error decayed_typeof +upon_error default_impls +upon_error impls_for +upon_error movable_value +upon_error sender +upon_error sender_adaptor_closure +upon_error set_error +upon_error try_set_value +upon_stopped decayed_typeof +upon_stopped default_impls +upon_stopped impls_for +upon_stopped movable_value +upon_stopped sender +upon_stopped sender_adaptor_closure +upon_stopped set_stopped +upon_stopped try_set_value +valid_completion_for callable +value_signature set_value +value_type_of_t completion_signatures_of_t +value_type_of_t gather_signatures +value_type_of_t set_value_t +variant_or_empty empty_variant +when_all default_domain +when_all emplace_value +when_all empty_env +when_all env_of_t +when_all get_domain +when_all get_domain_early +when_all get_env +when_all get_stop_token +when_all join_env +when_all make_env +when_all make_sender +when_all make_state +when_all sender +when_all set_error +when_all set_stopped +when_all set_value +when_all stop_callback_of_t +when_all stop_token_of_t +when_all transform_sender +when_all value_types_of_t +when_all_with_variant into_variant +when_all_with_variant when_all +with_awaitable_senders as_awaitable +write_env make_sender +write_env queryable \ No newline at end of file From 96b5f8bc3767aec532ad3d6e64f06241c8613484 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Sun, 25 Aug 2024 15:41:04 +0100 Subject: [PATCH 13/29] added default_impls --- docs/dependency.txt | 5 + .../Execution26/detail/default_impls.hpp | 63 +++++++ .../Execution26/detail/sender_decompose.hpp | 60 +++++++ .../Execution26/tests/exec-snd-expos.pass.cpp | 161 ++++++++++++++++++ 4 files changed, 289 insertions(+) create mode 100644 include/Beman/Execution26/detail/default_impls.hpp diff --git a/docs/dependency.txt b/docs/dependency.txt index 681f0315..b66fc8b9 100644 --- a/docs/dependency.txt +++ b/docs/dependency.txt @@ -89,6 +89,11 @@ continues_on sender_for default_domain queryable default_domain sender default_domain tag_of_t +default_impls fwd_env +default_impls get_env +default_impls empty_env +default_impls start +default_impls callable default_set_error completion_signatures default_set_error set_value default_set_value completion_signatures diff --git a/include/Beman/Execution26/detail/default_impls.hpp b/include/Beman/Execution26/detail/default_impls.hpp new file mode 100644 index 00000000..47b06f51 --- /dev/null +++ b/include/Beman/Execution26/detail/default_impls.hpp @@ -0,0 +1,63 @@ +// include/Beman/Execution26/detail/default_impls.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_DEFAULT_IMPLS +#define INCLUDED_BEMAN_EXECUTION26_DETAIL_DEFAULT_IMPLS + +#include +#include +#include +#include +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- + +namespace Beman::Execution26::Detail +{ + struct default_impls + { + static constexpr auto get_attrs + = [](auto const&, auto const&... child) noexcept -> decltype(auto) + { + if constexpr (1 == sizeof...(child)) + return (::Beman::Execution26::Detail::fwd_env( + ::Beman::Execution26::get_env(child) + ), ...); + else + return ::Beman::Execution26::empty_env{}; + }; + static constexpr auto get_env + = [](auto, auto&, auto const& receiver) noexcept -> decltype(auto) + { + return ::Beman::Execution26::Detail::fwd_env( + ::Beman::Execution26::get_env(receiver) + ); + }; + static constexpr auto get_state + = [](Sender&& sender, Receiver&) noexcept -> decltype(auto) + { + auto&& decompose = ::Beman::Execution26::Detail::get_sender_data(::std::forward(sender)); + return ::std::forward_like(decompose.data); + }; + static constexpr auto start + = [](auto&, auto&, auto&... ops) noexcept -> void + { + (::Beman::Execution26::start(ops), ...); + }; + static constexpr auto complete + = []( + Index, auto&, Receiver& receiver, Tag, Args&&... args) noexcept -> void + requires ::Beman::Execution26::Detail::callable + { + static_assert(Index::value == 0); + Tag()(::std::move(receiver), ::std::forward(args)...); + }; + }; +} + +// ---------------------------------------------------------------------------- + +#endif diff --git a/include/Beman/Execution26/detail/sender_decompose.hpp b/include/Beman/Execution26/detail/sender_decompose.hpp index 273f934e..0c8b3f2d 100644 --- a/include/Beman/Execution26/detail/sender_decompose.hpp +++ b/include/Beman/Execution26/detail/sender_decompose.hpp @@ -6,6 +6,7 @@ #include #include +#include // ---------------------------------------------------------------------------- @@ -24,6 +25,14 @@ namespace Beman::Execution26::Detail using children_type = ::std::remove_cvref_t; }; + template + struct sender_data + { + ::std::remove_cvref_t tag; + Data& data; + Children children; + }; + template auto get_sender_meta(Sender&& sender) { @@ -64,6 +73,57 @@ namespace Beman::Execution26::Detail return ::Beman::Execution26::Detail::sender_meta{}; } } + + template + auto get_sender_data(Sender&& sender) + { + #if 0 + //-dk:TODO should use a dynamic/language approach: + auto&& [tag, data, ... children] = sender; + return sender_meta>; + #endif + using sender_type = ::std::remove_cvref_t; + static constexpr ::Beman::Execution26::Detail::sender_any_t any{}; + if constexpr (requires(){ sender_type{ any, any, any, any, any, any }; }) + { + auto&& [tag, data, c0, c1, c2, c3] = sender; + return ::Beman::Execution26::Detail::sender_data{ + tag, data, ::std::tie(c0, c1, c2, c3) + }; + } + else if constexpr (requires(){ sender_type{ any, any, any, any, any }; }) + { + auto&& [tag, data, c0, c1, c2] = sender; + return ::Beman::Execution26::Detail::sender_data{ + tag, data, ::std::tie(c0, c1, c2) + }; + } + else if constexpr (requires(){ sender_type{ any, any, any, any }; }) + { + auto&& [tag, data, c0, c1] = sender; + return ::Beman::Execution26::Detail::sender_data{ + tag, data, ::std::tie(c0, c1) + }; + } + else if constexpr (requires(){ sender_type{ any, any, any }; }) + { + auto&& [tag, data, c0] = sender; + return ::Beman::Execution26::Detail::sender_data{ + tag, data, ::std::tie(c0) + }; + } + else if constexpr (requires(){ sender_type{ any, any }; }) + { + auto&& [tag, data] = sender; + return ::Beman::Execution26::Detail::sender_data>{ + tag, data, ::std::tuple<>() + }; + } + else + { + return ::Beman::Execution26::Detail::sender_meta{}; + } + } } namespace Beman::Execution26 diff --git a/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp b/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp index 6da0c2b7..7e0816cd 100644 --- a/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp +++ b/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -317,6 +318,165 @@ namespace //-dk:TOO test #endif } + + auto test_default_impls_get_attrs() -> void + { + struct env { int value; }; + struct child1 { auto get_env() const noexcept { return env{1}; } }; + struct child2 { auto get_env() const noexcept { return env{2}; } }; + + static_assert(noexcept(test_detail::default_impls::get_attrs(0, child1{}))); + static_assert(std::same_as, + decltype(test_detail::default_impls::get_attrs(0, child1{}))>); + static_assert(std::same_as); + } + + auto test_default_impls_get_env() -> void + { + struct env { int value; }; + struct receiver { auto get_env() const noexcept { return env{1}; } }; + + int arg{}; + static_assert(noexcept(test_detail::default_impls::get_env(0, arg, receiver{}))); + static_assert(std::same_as, + decltype(test_detail::default_impls::get_env(0, arg, receiver{}))>); + } + + auto test_default_impls_get_state() -> void + { + struct tag {}; + struct data + { + int v1{}; int v2{}; + auto operator== (data const&) const -> bool = default; + }; + struct sender0 + { + tag t; + data d{1, 2}; + }; + struct sender1 + { + tag t; + data d{1, 2}; + int i1; + }; + struct sender2 + { + tag t; + data d{1, 2}; + int i1; + int i2; + }; + struct sender3 + { + tag t; + data d{1, 2}; + int i1; + int i2; + int i3; + }; + struct sender4 + { + tag t; + data d{1, 2}; + int i1; + int i2; + int i3; + int i4; + }; + struct receiver + { + }; + + sender0 s{}; + sender0 const cs{}; + receiver r{}; + static_assert(noexcept(test_detail::default_impls::get_state(sender0{}, r))); + static_assert(std::same_as); + assert((data{1, 2}) == test_detail::default_impls::get_state(sender0{}, r)); + static_assert(std::same_as); + assert((data{1, 2}) == test_detail::default_impls::get_state(sender1{}, r)); + static_assert(std::same_as); + assert((data{1, 2}) == test_detail::default_impls::get_state(sender2{}, r)); + static_assert(std::same_as); + assert((data{1, 2}) == test_detail::default_impls::get_state(sender3{}, r)); + static_assert(std::same_as); + assert((data{1, 2}) == test_detail::default_impls::get_state(sender4{}, r)); + static_assert(std::same_as); + static_assert(std::same_as); + } + auto test_default_impls_start() -> void + { + struct state + { + bool called{false}; + auto start() noexcept -> void { called = true; } + }; + int a0{}; + int a1{}; + state s1; + state s2; + state s3; + state s4; + state s5; + static_assert(noexcept(test_detail::default_impls::start(a0, a1, s1, s2, s3, s4, s5))); + assert(s1.called == false); + assert(s2.called == false); + assert(s3.called == false); + assert(s4.called == false); + assert(s5.called == false); + test_detail::default_impls::start(a0, a1, s1, s2, s3, s4, s5); + assert(s1.called == true); + assert(s2.called == true); + assert(s3.called == true); + assert(s4.called == true); + assert(s5.called == true); + } + template + auto test_default_impls_complete(Impls) -> void + { + struct arg {}; + struct receiver { bool& called; }; + struct state {}; + + bool called{false}; + auto non_tag = [](receiver&&, int){}; + auto tag = [](receiver&& r, int, arg){ r.called = true; }; + receiver r{called}; + state s{}; + + static_assert(not requires{ + Impls::complete(::std::integral_constant{}, s, r, non_tag, 0, arg{}); + }); + static_assert(requires{ + Impls::complete(::std::integral_constant{}, s, r, tag, 0, arg{}); + }); + static_assert(noexcept( + Impls::complete(::std::integral_constant{}, s, r, tag, 0, arg{}) + )); + + assert(r.called == false); + Impls::complete(::std::integral_constant{}, s, r, tag, 0, arg{}); + assert(r.called == true); + } + + auto test_default_impls() -> void + { + test_default_impls_get_attrs(); + test_default_impls_get_env(); + test_default_impls_get_state(); + test_default_impls_start(); + test_default_impls_complete(test_detail::default_impls{}); + } } auto main() -> int @@ -329,4 +489,5 @@ auto main() -> int test_completion_domain(); test_query_with_default(); test_get_domain_late(); + test_default_impls(); } \ No newline at end of file From ea56d995486b44f67dfe4e7d5462a6b4c0411fb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Sun, 25 Aug 2024 15:56:28 +0100 Subject: [PATCH 14/29] work-around for gcc apparently missing forward_like --- .../Execution26/detail/default_impls.hpp | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/include/Beman/Execution26/detail/default_impls.hpp b/include/Beman/Execution26/detail/default_impls.hpp index 47b06f51..92e0230c 100644 --- a/include/Beman/Execution26/detail/default_impls.hpp +++ b/include/Beman/Execution26/detail/default_impls.hpp @@ -17,6 +17,55 @@ namespace Beman::Execution26::Detail { +#if __cpp_lib_forward_like < 202207 + template + struct forward_like_helper + { + template + static auto forward(U&& u) -> ::std::remove_cvref_t&& + { + return ::std::forward(u); + } + }; + template + struct forward_like_helper + { + template + static auto forward(U&& u) -> ::std::remove_cvref_t& + { + return ::std::forward(u); + } + }; + template + struct forward_like_helper + { + template + static auto forward(U&& u) -> ::std::remove_cvref_t const&& + { + return ::std::forward(u); + } + }; + template + struct forward_like_helper + { + template + static auto forward(U&& u) -> ::std::remove_cvref_t const& + { + return ::std::forward(u); + } + }; +#endif + + template + auto forward_like(U&& u) noexcept -> decltype(auto) + { +#if 202207 <= __cpp_lib_forward_like + return ::std::forward_like(::std::forward(u)); +#else + return ::Beman::Execution26::Detail::forward_like_helper::forward(::std::forward(u)); +#endif + } + struct default_impls { static constexpr auto get_attrs From af33377099b22cfd24af6b60b60b5c4a6810213f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Sun, 25 Aug 2024 15:59:56 +0100 Subject: [PATCH 15/29] fixed the forward_like work-around --- include/Beman/Execution26/detail/default_impls.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/Beman/Execution26/detail/default_impls.hpp b/include/Beman/Execution26/detail/default_impls.hpp index 92e0230c..8cb87235 100644 --- a/include/Beman/Execution26/detail/default_impls.hpp +++ b/include/Beman/Execution26/detail/default_impls.hpp @@ -24,7 +24,7 @@ namespace Beman::Execution26::Detail template static auto forward(U&& u) -> ::std::remove_cvref_t&& { - return ::std::forward(u); + return ::std::move(u); } }; template @@ -42,7 +42,7 @@ namespace Beman::Execution26::Detail template static auto forward(U&& u) -> ::std::remove_cvref_t const&& { - return ::std::forward(u); + return ::std::move(u); } }; template @@ -89,7 +89,7 @@ namespace Beman::Execution26::Detail = [](Sender&& sender, Receiver&) noexcept -> decltype(auto) { auto&& decompose = ::Beman::Execution26::Detail::get_sender_data(::std::forward(sender)); - return ::std::forward_like(decompose.data); + return ::Beman::Execution26::Detail::forward_like(decompose.data); }; static constexpr auto start = [](auto&, auto&, auto&... ops) noexcept -> void From 7a16c7ef8b1020bfcb1e1c1592adba6d16af86ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Sun, 25 Aug 2024 19:08:47 +0100 Subject: [PATCH 16/29] added impls_for --- docs/dependency.txt | 13 +++++------ .../Beman/Execution26/detail/impls_for.hpp | 22 +++++++++++++++++++ .../Execution26/tests/exec-snd-expos.pass.cpp | 10 +++++++++ 3 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 include/Beman/Execution26/detail/impls_for.hpp diff --git a/docs/dependency.txt b/docs/dependency.txt index b66fc8b9..62006374 100644 --- a/docs/dependency.txt +++ b/docs/dependency.txt @@ -21,7 +21,6 @@ basic_operation tag_of_t basic_operation valid_specialization basic_receiver basic_state basic_receiver callable -basic_receiver complete basic_receiver impls_for basic_receiver receiver_t basic_receiver set_error @@ -55,7 +54,7 @@ completion_signature set_stopped completion_signature set_value completion_signatures_for completion_signatures completion_tag set_error -completion_tag set_set_stopped +completion_tag set_stopped completion_tag set_value connect env_of_t connect get_domain_late @@ -140,7 +139,7 @@ get_domain_late continues_on_t get_domain_late default_domain get_domain_late get_domain get_domain_late get_scheduler -get_domain_late query_or_default +get_domain_late query_with_default get_domain_late sender_for get_env empty_env get_env mandate_nothrow @@ -272,7 +271,7 @@ on get_domain on get_env on get_scheduler on make_sender -on query_or_default +on query_with_default on sched_env on scheduler on sender @@ -331,7 +330,7 @@ schedule_from impls_for schedule_from join_env schedule_from make_sender schedule_from op_state -schedule_from query_or_default +schedule_from query_with_default schedule_from receiver_t schedule_from sched_attrs schedule_from sched_t @@ -404,7 +403,7 @@ starts_on get_domain starts_on join_env starts_on let_value starts_on make_sender -starts_on query_or_default +starts_on query_with_default starts_on sched_env starts_on schedule starts_on scheduler @@ -509,4 +508,4 @@ when_all_with_variant into_variant when_all_with_variant when_all with_awaitable_senders as_awaitable write_env make_sender -write_env queryable \ No newline at end of file +write_env queryable diff --git a/include/Beman/Execution26/detail/impls_for.hpp b/include/Beman/Execution26/detail/impls_for.hpp new file mode 100644 index 00000000..3ce223d6 --- /dev/null +++ b/include/Beman/Execution26/detail/impls_for.hpp @@ -0,0 +1,22 @@ +// include/Beman/Execution26/detail/impls_for.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_IMPLS_FOR +#define INCLUDED_BEMAN_EXECUTION26_DETAIL_IMPLS_FOR + +#include + +// ---------------------------------------------------------------------------- + +namespace Beman::Execution26::Detail +{ + template + struct impls_for + : ::Beman::Execution26::Detail::default_impls + { + }; +} + +// ---------------------------------------------------------------------------- + +#endif diff --git a/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp b/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp index 7e0816cd..49db8e8a 100644 --- a/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp +++ b/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -477,6 +478,14 @@ namespace test_default_impls_start(); test_default_impls_complete(test_detail::default_impls{}); } + + auto test_impls_for() + { + struct tag {}; + + static_assert(std::derived_from, + test_detail::default_impls>); + } } auto main() -> int @@ -490,4 +499,5 @@ auto main() -> int test_query_with_default(); test_get_domain_late(); test_default_impls(); + test_impls_for(); } \ No newline at end of file From ea28d98ca2edf1a07b6ae8c654a911c9e48f2911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Sun, 25 Aug 2024 19:27:34 +0100 Subject: [PATCH 17/29] added state_type --- docs/questions.md | 2 +- .../Beman/Execution26/detail/state_type.hpp | 28 +++++++++++++++++++ .../Execution26/tests/exec-snd-expos.pass.cpp | 18 +++++++++++- 3 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 include/Beman/Execution26/detail/state_type.hpp diff --git a/docs/questions.md b/docs/questions.md index 386cc19b..53606184 100644 --- a/docs/questions.md +++ b/docs/questions.md @@ -15,7 +15,7 @@ likely observable. - [exec.fwd.env] states "Mandates: ... is a core constant expression if `q` is a core constant expression": I don't know how to possibly implement that. -- [exec.snd.expos] uses query-or-default; it seems only query-with-default +- done: [exec.snd.expos] uses query-or-default; it seems only query-with-default is defined. - [exec.snd.concepts] "The type tag_of_t is +defined+ as follows:" - [exec.sched] uses `auto(get_completion_scheduler(...))` diff --git a/include/Beman/Execution26/detail/state_type.hpp b/include/Beman/Execution26/detail/state_type.hpp new file mode 100644 index 00000000..484e6fcf --- /dev/null +++ b/include/Beman/Execution26/detail/state_type.hpp @@ -0,0 +1,28 @@ +// include/Beman/Execution26/detail/state_type.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_STATE_TYPE +#define INCLUDED_BEMAN_EXECUTION26_DETAIL_STATE_TYPE + +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- + +namespace Beman::Execution26::Detail +{ + template + using state_type = ::std::decay_t< + ::Beman::Execution26::Detail::call_result_t< + decltype(::Beman::Execution26::Detail::impls_for< + ::Beman::Execution26::tag_of_t + >::get_state), Sender, Receiver& + > + >; +} + +// ---------------------------------------------------------------------------- + +#endif diff --git a/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp b/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp index 49db8e8a..ce880e26 100644 --- a/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp +++ b/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -479,13 +480,27 @@ namespace test_default_impls_complete(test_detail::default_impls{}); } - auto test_impls_for() + auto test_impls_for() -> void { struct tag {}; static_assert(std::derived_from, test_detail::default_impls>); } + + auto test_state_type() -> void + { + struct tag {}; + struct state {}; + struct sender + { + tag t; + state s; + }; + struct receiver {}; + + static_assert(std::same_as>); + } } auto main() -> int @@ -500,4 +515,5 @@ auto main() -> int test_get_domain_late(); test_default_impls(); test_impls_for(); + test_state_type(); } \ No newline at end of file From fbd3d004c395ed7b1849f0dc661b01764d92b5d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Sun, 25 Aug 2024 20:07:47 +0100 Subject: [PATCH 18/29] added basic_state --- .../Beman/Execution26/detail/basic_state.hpp | 34 +++++++++++++++++++ .../Execution26/tests/exec-snd-expos.pass.cpp | 16 +++++++++ 2 files changed, 50 insertions(+) create mode 100644 include/Beman/Execution26/detail/basic_state.hpp diff --git a/include/Beman/Execution26/detail/basic_state.hpp b/include/Beman/Execution26/detail/basic_state.hpp new file mode 100644 index 00000000..7f3541d1 --- /dev/null +++ b/include/Beman/Execution26/detail/basic_state.hpp @@ -0,0 +1,34 @@ +// include/Beman/Execution26/detail/basic_state.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_BASIC_STATE +#define INCLUDED_BEMAN_EXECUTION26_DETAIL_BASIC_STATE + +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- + +namespace Beman::Execution26::Detail +{ + template + struct basic_state + { + basic_state(Sender&& sender, Receiver&& receiver) noexcept(true) + : receiver(::std::move(receiver)) + , state(::Beman::Execution26::Detail::impls_for< + ::Beman::Execution26::tag_of_t + >::get_state(::std::forward(sender), receiver)) + { + } + + Receiver receiver; + ::Beman::Execution26::Detail::state_type state; + }; +} + +// ---------------------------------------------------------------------------- + +#endif diff --git a/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp b/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp index ce880e26..be437a16 100644 --- a/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp +++ b/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -501,6 +502,20 @@ namespace static_assert(std::same_as>); } + + auto test_basic_state() -> void + { + struct tag {}; + struct data {}; + struct sender + { + tag t; + data d; + }; + struct receiver {}; + + test_detail::basic_state state(sender{}, receiver{}); + } } auto main() -> int @@ -516,4 +531,5 @@ auto main() -> int test_default_impls(); test_impls_for(); test_state_type(); + test_basic_state(); } \ No newline at end of file From f61e9e1602b06bbe0ecc778ea4460c56eae7d357 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Sun, 25 Aug 2024 20:32:31 +0100 Subject: [PATCH 19/29] added indices_for --- .../Beman/Execution26/detail/indices_for.hpp | 19 +++++++++++++++++++ .../Execution26/tests/exec-snd-expos.pass.cpp | 17 +++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 include/Beman/Execution26/detail/indices_for.hpp diff --git a/include/Beman/Execution26/detail/indices_for.hpp b/include/Beman/Execution26/detail/indices_for.hpp new file mode 100644 index 00000000..635e3d49 --- /dev/null +++ b/include/Beman/Execution26/detail/indices_for.hpp @@ -0,0 +1,19 @@ +// include/Beman/Execution26/detail/indices_for.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_INDICES_FOR +#define INCLUDED_BEMAN_EXECUTION26_DETAIL_INDICES_FOR + +#include + +// ---------------------------------------------------------------------------- + +namespace Beman::Execution26::Detail +{ + template + using indices_for = ::std::remove_reference_t::indices_for; +} + +// ---------------------------------------------------------------------------- + +#endif diff --git a/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp b/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp index be437a16..fda89621 100644 --- a/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp +++ b/src/Beman/Execution26/tests/exec-snd-expos.pass.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -516,6 +517,21 @@ namespace test_detail::basic_state state(sender{}, receiver{}); } + + auto test_indices_for() -> void + { + using indices = ::std::make_index_sequence<5>; + struct sender + { + using indices_for = indices; + }; + + static_assert(::std::same_as>); + static_assert(::std::same_as>); + static_assert(::std::same_as>); + static_assert(::std::same_as>); + static_assert(::std::same_as>); + } } auto main() -> int @@ -532,4 +548,5 @@ auto main() -> int test_impls_for(); test_state_type(); test_basic_state(); + test_indices_for(); } \ No newline at end of file From effe6a18ef60d414718f53e56fafc7a973366d6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dietmar=20K=C3=BChl?= Date: Sun, 25 Aug 2024 20:42:55 +0100 Subject: [PATCH 20/29] added valid_specialization --- .../detail/valid_specialization.hpp | 19 +++++++++++++++++++ .../Execution26/tests/exec-snd-expos.pass.cpp | 11 +++++++++++ 2 files changed, 30 insertions(+) create mode 100644 include/Beman/Execution26/detail/valid_specialization.hpp diff --git a/include/Beman/Execution26/detail/valid_specialization.hpp b/include/Beman/Execution26/detail/valid_specialization.hpp new file mode 100644 index 00000000..4ed0922a --- /dev/null +++ b/include/Beman/Execution26/detail/valid_specialization.hpp @@ -0,0 +1,19 @@ +// include/Beman/Execution26/detail/valid_specialization.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_BEMAN_EXECUTION26_DETAIL_VALID_SPECIALIZATION +#define INCLUDED_BEMAN_EXECUTION26_DETAIL_VALID_SPECIALIZATION + +// ---------------------------------------------------------------------------- + +namespace Beman::Execution26::Detail +{ + template