diff --git a/docs/implementation-status.md b/docs/implementation-status.md index cc64333e..c7cbd2e1 100644 --- a/docs/implementation-status.md +++ b/docs/implementation-status.md @@ -1,3 +1,6 @@ + # Implementation Status Meaning of the status indicators (in order best to worst): @@ -15,13 +18,13 @@ The indicators come in groups of threes: Each section containing subelements reflects the state of the "worst" element. # 🔴🔴🔴 [exec](https://wg21.link/exec) Execution control library -## 🚧✅✅ [exec.general](https://wg21.link/exec.general) General +## ✅✅✅ [exec.general](https://wg21.link/exec.general) General -- 🚧❎❎ [MANDATE-NOTHROW(expr)](https://wg21.link/exec.general#5) ⇒ noexcept(expr) is `true` +- ❎❎❎ [MANDATE-NOTHROW(expr)](https://wg21.link/exec.general#5) ⇒ noexcept(expr) is `true` - ✅✅✅ [movable-value<T>](https://wg21.link/exec.general#6): [`movable_value.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/movable_value.hpp) - ✅✅✅ [MATCHING-SIG<F1, F2>](https://wg21.link/exec.general#7): [`matching_sig.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/matching_sig.hpp) - ✅✅✅ [AS-EXCEPT-PTR(error)](https://wg21.link/exec.general#8): [`as_except_ptr.hpp`](https://github.com/bemanproject/execution/blob/main/include/beman/execution/detail/as_except_ptr.hpp) -- 🚧❎❎ [as-const(error)](https://wg21.link/exec.general#9): [std::as_const](https://wg21.link/utility.as.const)(error) +- ❎❎❎ [as-const(error)](https://wg21.link/exec.general#9): [std::as_const](https://wg21.link/utility.as.const)(error) ## 🚧✅✅ [exec.queryable](https://wg21.link/exec.queryable) Query and queryables ### 🚧❎❎ [exec.queryable.general](https://wg21.link/exec.queryable.general) General diff --git a/docs/overview.md b/docs/overview.md index 955c8d86..7a4c9cc6 100644 --- a/docs/overview.md +++ b/docs/overview.md @@ -821,10 +821,11 @@ tries the following transformations:
  • sender-awaitable{adapt-for-await-completion(transform_sender(expr, get_env(promise))), promise} if this expression is well-formed; otherwise
  • expr
  • - + - `with_awaitable_sender` - `apply_sender` +
    completion_signatures<Sig...> The template specialization completion_signatures<Sig...> is a list diff --git a/include/beman/execution/detail/forwarding_query.hpp b/include/beman/execution/detail/forwarding_query.hpp index bf22ea34..634c9dde 100644 --- a/include/beman/execution/detail/forwarding_query.hpp +++ b/include/beman/execution/detail/forwarding_query.hpp @@ -24,9 +24,10 @@ namespace beman::execution::detail { struct forwarding_query_t { template requires requires(Object&& object, const forwarding_query_t& query) { - { ::std::forward(object).query(query) } noexcept -> ::std::same_as; + { ::std::forward(object).query(query) } -> ::std::same_as; } constexpr auto operator()(Object&& object) const noexcept -> bool { + static_assert(noexcept(::std::forward(object).query(*this))); return ::std::forward(object).query(*this); } template diff --git a/include/beman/execution/detail/get_await_completion_adaptor.hpp b/include/beman/execution/detail/get_await_completion_adaptor.hpp index d0a7cf5e..d8e79ac0 100644 --- a/include/beman/execution/detail/get_await_completion_adaptor.hpp +++ b/include/beman/execution/detail/get_await_completion_adaptor.hpp @@ -21,10 +21,9 @@ import beman.execution.detail.forwarding_query; namespace beman::execution { struct get_await_completion_adaptor_t { template - requires requires(Env&& env, const get_await_completion_adaptor_t& g) { - { ::std::as_const(env).query(g) } noexcept; - } + requires requires(Env&& env, const get_await_completion_adaptor_t& g) { ::std::as_const(env).query(g); } auto operator()(Env&& env) const noexcept { + static_assert(noexcept(::std::as_const(env).query(*this))); return ::std::as_const(env).query(*this); } static constexpr auto query(const ::beman::execution::forwarding_query_t&) noexcept -> bool { return true; } diff --git a/include/beman/execution/detail/get_completion_scheduler.hpp b/include/beman/execution/detail/get_completion_scheduler.hpp index cb7cba53..62bf5394 100644 --- a/include/beman/execution/detail/get_completion_scheduler.hpp +++ b/include/beman/execution/detail/get_completion_scheduler.hpp @@ -80,6 +80,8 @@ template ::beman::execution::scheduler auto get_completion_scheduler_t::operator()(const Q& q, const E&... e) const noexcept { if constexpr (::beman::execution::detail::compl_sched_recurse_queryable) { + static_assert(noexcept( + ::beman::execution::detail::recurse_query(::beman::execution::detail::try_query(q, *this, e...), e...))); return ::beman::execution::detail::recurse_query(::beman::execution::detail::try_query(q, *this, e...), e...); } else { static_assert(::beman::execution::scheduler); diff --git a/include/beman/execution/detail/get_delegation_scheduler.hpp b/include/beman/execution/detail/get_delegation_scheduler.hpp index 7c070e06..9364b9d3 100644 --- a/include/beman/execution/detail/get_delegation_scheduler.hpp +++ b/include/beman/execution/detail/get_delegation_scheduler.hpp @@ -24,9 +24,10 @@ namespace beman::execution { struct get_delegation_scheduler_t { template requires requires(Env&& env, const get_delegation_scheduler_t& g) { - { auto(::std::as_const(env).query(g)) } noexcept -> ::beman::execution::scheduler; + { auto(::std::as_const(env).query(g)) } -> ::beman::execution::scheduler; } auto operator()(Env&& env) const noexcept { + static_assert(noexcept(::std::as_const(env).query(*this))); return ::std::as_const(env).query(*this); } constexpr auto query(const ::beman::execution::forwarding_query_t&) const noexcept -> bool { return true; } diff --git a/include/beman/execution/detail/get_domain.hpp b/include/beman/execution/detail/get_domain.hpp index d774a526..1572e7a9 100644 --- a/include/beman/execution/detail/get_domain.hpp +++ b/include/beman/execution/detail/get_domain.hpp @@ -35,14 +35,27 @@ struct get_domain_t : ::beman::execution::forwarding_query_t { template constexpr auto operator()(Env&& env) const noexcept { if constexpr (requires { ::std::as_const(env).query(*this); }) { - return ::std::as_const(env).query(*this); + using type = decltype(auto(::std::as_const(env).query(*this))); + static_assert(noexcept(type{})); + return type{}; } else if constexpr (requires { ::beman::execution::get_completion_domain<::beman::execution::set_value_t>( ::beman::execution::get_scheduler(env), ::beman::execution::detail::hide_sched(env)); }) { - return ::beman::execution::get_completion_domain<::beman::execution::set_value_t>( - ::beman::execution::get_scheduler(env), ::beman::execution::detail::hide_sched(env)); + using type = decltype(auto(::beman::execution::get_completion_domain<::beman::execution::set_value_t>( + ::beman::execution::get_scheduler(env), ::beman::execution::detail::hide_sched(env)))); + static_assert(noexcept(type{})); + return type{}; + } else if constexpr (requires { + ::beman::execution::get_completion_domain<::beman::execution::set_value_t>( + ::beman::execution::get_scheduler(env), + ::beman::execution::detail::hide_sched(env)); + }) { + using type = decltype(auto(::beman::execution::get_completion_domain<::beman::execution::set_value_t>( + ::beman::execution::get_scheduler(env), ::beman::execution::detail::hide_sched(env)))); + static_assert(noexcept(type{})); + return type{}; } else { return ::beman::execution::default_domain{}; } diff --git a/include/beman/execution/detail/get_env.hpp b/include/beman/execution/detail/get_env.hpp index cfb910c4..52fcb32a 100644 --- a/include/beman/execution/detail/get_env.hpp +++ b/include/beman/execution/detail/get_env.hpp @@ -29,11 +29,12 @@ struct get_env_t { std::remove_cvref_t&>().get_env())>>) auto operator()(Object&& object) const noexcept -> decltype(auto) { ::std::add_const_t<::std::remove_cvref_t>& obj{object}; - if constexpr (requires { obj.get_env(); }) { - static_assert(noexcept(obj.get_env()), "get_env requires the expression to be noexcept"); - static_assert(::beman::execution::detail::queryable>, - "get_env requires the result type to be destructible"); - return obj.get_env(); + if constexpr (requires { ::std::as_const(obj).get_env(); }) { + static_assert(noexcept(::std::as_const(obj).get_env()), "get_env requires the expression to be noexcept"); + static_assert( + ::beman::execution::detail::queryable>, + "get_env requires the result type to be destructible"); + return ::std::as_const(obj).get_env(); } else { return ::beman::execution::env<>{}; } diff --git a/include/beman/execution/detail/get_forward_progress_guarantee.hpp b/include/beman/execution/detail/get_forward_progress_guarantee.hpp index d11cc89e..eaba86b9 100644 --- a/include/beman/execution/detail/get_forward_progress_guarantee.hpp +++ b/include/beman/execution/detail/get_forward_progress_guarantee.hpp @@ -29,6 +29,7 @@ struct get_forward_progress_guarantee_t { template requires requires(const Object& object, const get_forward_progress_guarantee_t& tag) { object.query(tag); } auto operator()(const Object& object) const noexcept -> forward_progress_guarantee { + static_assert(noexcept(object.query(*this))); static_assert(::std::same_as); return object.query(*this); } diff --git a/include/beman/execution/detail/get_scheduler.hpp b/include/beman/execution/detail/get_scheduler.hpp index a0dc5c50..49d8bca3 100644 --- a/include/beman/execution/detail/get_scheduler.hpp +++ b/include/beman/execution/detail/get_scheduler.hpp @@ -33,6 +33,8 @@ struct get_scheduler_t : ::beman::execution::forwarding_query_t { ::std::as_const(env).query(self), ::beman::execution::detail::hide_sched(env)); } auto operator()(Env&& env) const noexcept { + static_assert(noexcept(::beman::execution::get_completion_scheduler<::beman::execution::set_value_t>( + ::std::as_const(env).query(*this), ::beman::execution::detail::hide_sched(env)))); return ::beman::execution::get_completion_scheduler<::beman::execution::set_value_t>( ::std::as_const(env).query(*this), ::beman::execution::detail::hide_sched(env)); } diff --git a/include/beman/execution/detail/get_start_scheduler.hpp b/include/beman/execution/detail/get_start_scheduler.hpp index 43a00bbf..5df9e5b8 100644 --- a/include/beman/execution/detail/get_start_scheduler.hpp +++ b/include/beman/execution/detail/get_start_scheduler.hpp @@ -24,10 +24,11 @@ namespace beman::execution { struct get_start_scheduler_t : ::beman::execution::forwarding_query_t { template requires requires(const get_start_scheduler_t& self, const Env& env) { - { auto(::std::as_const(env).query(self)) } noexcept -> beman::execution::scheduler; + { auto(::std::as_const(env).query(self)) } -> beman::execution::scheduler; } auto operator()(const Env& env) const noexcept { - return env.query(*this); + static_assert(noexcept(::std::as_const(env).query(*this))); + return ::std::as_const(env).query(*this); } }; diff --git a/include/beman/execution/detail/get_stop_token.hpp b/include/beman/execution/detail/get_stop_token.hpp index 010eb294..bed41dc9 100644 --- a/include/beman/execution/detail/get_stop_token.hpp +++ b/include/beman/execution/detail/get_stop_token.hpp @@ -31,9 +31,10 @@ namespace beman::execution { struct get_stop_token_t { template requires requires(Object&& object, const get_stop_token_t& tag) { - { ::std::as_const(object).query(tag) } noexcept -> ::beman::execution::detail::decayed_stoppable_token; + { ::std::as_const(object).query(tag) } -> ::beman::execution::detail::decayed_stoppable_token; } auto operator()(Object&& object) const noexcept { + static_assert(noexcept(::std::as_const(object).query(*this))); return ::std::as_const(object).query(*this); } diff --git a/include/beman/execution/detail/set_error.hpp b/include/beman/execution/detail/set_error.hpp index 83040252..b3764ed9 100644 --- a/include/beman/execution/detail/set_error.hpp +++ b/include/beman/execution/detail/set_error.hpp @@ -32,14 +32,12 @@ struct set_error_t { ::std::forward(receiver).set_error(::std::forward(error)); }) = BEMAN_EXECUTION_DELETE("set_error requires a suitable member overload on the receiver"); - template - requires(not noexcept(::std::declval().set_error(::std::declval()))) - auto operator()(Receiver&&, Error&&) const - -> void = BEMAN_EXECUTION_DELETE("the call to receiver.set_error(error) has to be noexcept"); // NOLINTBEGIN(misc-no-recursion) template auto operator()(Receiver&& receiver, Error&& error) const noexcept -> void { + static_assert(noexcept(::std::forward(receiver).set_error(::std::forward(error))), + "the call to receiver.set_error(error) has to be noexcept"); ::std::forward(receiver).set_error(::std::forward(error)); } // NOLINTEND(misc-no-recursion) diff --git a/include/beman/execution/detail/set_stopped.hpp b/include/beman/execution/detail/set_stopped.hpp index d0061cab..1f803937 100644 --- a/include/beman/execution/detail/set_stopped.hpp +++ b/include/beman/execution/detail/set_stopped.hpp @@ -30,13 +30,11 @@ struct set_stopped_t { auto operator()(Receiver&&) const -> void requires(not requires(Receiver&& receiver) { ::std::forward(receiver).set_stopped(); }) = BEMAN_EXECUTION_DELETE("set_stopped requires a suitable member overload on the receiver"); - template - requires(not noexcept(::std::declval().set_stopped())) - auto operator()(Receiver&&) const - -> void = BEMAN_EXECUTION_DELETE("the call to receiver.set_stopped() has to be noexcept"); template auto operator()(Receiver&& receiver) const noexcept -> void { + static_assert(noexcept(::std::forward(receiver).set_stopped()), + "the call to receiver.set_stopped() has to be noexcept"); ::std::forward(receiver).set_stopped(); } }; diff --git a/include/beman/execution/detail/set_value.hpp b/include/beman/execution/detail/set_value.hpp index c2e4bdc4..4cf48a97 100644 --- a/include/beman/execution/detail/set_value.hpp +++ b/include/beman/execution/detail/set_value.hpp @@ -50,6 +50,9 @@ struct set_value_t { template auto operator()(Receiver&& receiver, Args&&... args) const noexcept -> void { + static_assert(noexcept(::std::forward(receiver).set_value(::std::forward(args)...)), + "the call to receiver.set_value(args...) has to be noexcept"); + ::std::forward(receiver).set_value(::std::forward(args)...); } }; diff --git a/include/beman/execution/detail/start.hpp b/include/beman/execution/detail/start.hpp index 546a7314..0e074bb5 100644 --- a/include/beman/execution/detail/start.hpp +++ b/include/beman/execution/detail/start.hpp @@ -20,24 +20,15 @@ struct start_t { requires(not requires(const State& state) { state.start(); }) auto operator()(const State&) const -> void = BEMAN_EXECUTION_DELETE("state needs to have a start() member"); - template - requires(not requires(State& state) { - { state.start() } noexcept; - }) - auto operator()(State&) const -> void = BEMAN_EXECUTION_DELETE("state start() member has to be noexcept"); - template - requires(not requires(const State& state) { - { state.start() } noexcept; - }) - auto operator()(const State&) const -> void = BEMAN_EXECUTION_DELETE("state start() member has to be noexcept"); - template auto operator()(const State& state) const noexcept -> void { + static_assert(noexcept(state.start()), "state start() member has to be noexcept"); state.start(); } // NOLINTBEGIN(misc-no-recursion) template auto operator()(State& state) const noexcept -> void { + static_assert(noexcept(state.start()), "state start() member has to be noexcept"); state.start(); } // NOLINTEND(misc-no-recursion) diff --git a/include/beman/execution/detail/stop_when.hpp b/include/beman/execution/detail/stop_when.hpp index 77cbe9e9..0d1a99d6 100644 --- a/include/beman/execution/detail/stop_when.hpp +++ b/include/beman/execution/detail/stop_when.hpp @@ -8,6 +8,7 @@ #ifdef BEMAN_HAS_IMPORT_STD import std; #else +#include #include #include #include @@ -67,24 +68,32 @@ struct beman::execution::detail::stop_when_t::sender { std::remove_cvref_t sndr; template <::beman::execution::receiver Rcvr> - struct state { + struct base_state { + using rcvr_t = ::std::remove_cvref_t; + rcvr_t rcvr; + ::beman::execution::inplace_stop_source source{}; + base_state(Rcvr&& r) : rcvr(::std::forward(r)) {} + virtual ~base_state() noexcept = default; + virtual auto reset() & noexcept -> void = 0; + }; + template <::beman::execution::receiver Rcvr> + struct state : base_state { using operation_state_concept = ::beman::execution::operation_state_tag; - using rcvr_t = ::std::remove_cvref_t; + using rcvr_t = base_state::rcvr_t; using token1_t = ::std::remove_cvref_t; using token2_t = decltype(::beman::execution::get_stop_token(::beman::execution::get_env(::std::declval()))); struct cb_t { ::beman::execution::inplace_stop_source& source; - auto operator()() const noexcept { this->source.request_stop(); } - }; - struct base_state { - rcvr_t rcvr; - ::beman::execution::inplace_stop_source source{}; + auto operator()() const noexcept { + ::std::cout << "stop_when: stop requested\n" << ::std::flush; + this->source.request_stop(); + } }; struct env { - base_state* st; - auto query(const ::beman::execution::get_stop_token_t&) const noexcept { + base_state* st; + auto query(const ::beman::execution::get_stop_token_t&) const noexcept { return this->st->source.get_token(); } template @@ -98,40 +107,48 @@ struct beman::execution::detail::stop_when_t::sender { struct receiver { using receiver_concept = ::beman::execution::receiver_tag; - base_state* st; + base_state* st; auto get_env() const noexcept -> env { return env{this->st}; } template auto set_value(A&&... a) const noexcept -> void { + this->st->reset(); ::beman::execution::set_value(::std::move(this->st->rcvr), ::std::forward(a)...); } template auto set_error(E&& e) const noexcept -> void { + this->st->reset(); ::beman::execution::set_error(::std::move(this->st->rcvr), ::std::forward(e)); } - auto set_stopped() const noexcept -> void { ::beman::execution::set_stopped(::std::move(this->st->rcvr)); } + auto set_stopped() const noexcept -> void { + this->st->reset(); + ::beman::execution::set_stopped(::std::move(this->st->rcvr)); + } }; using inner_state_t = decltype(::beman::execution::connect(::std::declval(), ::std::declval())); token1_t tok; - base_state base; std::optional<::beman::execution::stop_callback_for_t> cb1; std::optional<::beman::execution::stop_callback_for_t> cb2; inner_state_t inner_state; template <::beman::execution::sender S, ::beman::execution::stoppable_token T, ::beman::execution::receiver R> state(S&& s, T&& t, R&& r) - : tok(::std::forward(t)), - base{::std::forward(r)}, - inner_state(::beman::execution::connect(::std::forward(s), receiver{&this->base})) {} + : base_state{::std::forward(r)}, + tok(::std::forward(t)), + inner_state(::beman::execution::connect(::std::forward(s), receiver{this})) {} auto start() & noexcept { - this->cb1.emplace(this->tok, cb_t{this->base.source}); - this->cb2.emplace(::beman::execution::get_stop_token(::beman::execution::get_env(this->base.rcvr)), - cb_t{this->base.source}); + this->cb1.emplace(this->tok, cb_t{this->source}); + this->cb2.emplace(::beman::execution::get_stop_token(::beman::execution::get_env(this->rcvr)), + cb_t{this->source}); ::beman::execution::start(this->inner_state); } + auto reset() & noexcept -> void override { + this->cb1.reset(); + this->cb2.reset(); + } }; template diff --git a/tests/beman/execution/CMakeLists.txt b/tests/beman/execution/CMakeLists.txt index ef8464ad..0ff48cfb 100644 --- a/tests/beman/execution/CMakeLists.txt +++ b/tests/beman/execution/CMakeLists.txt @@ -5,7 +5,7 @@ if(BEMAN_USE_MODULES) list(APPEND execution_tests execution-module.test stop-token-module.test) endif() -list(APPEND unsupported_execution_tests exec-split.test exec-spawn-future.test) +list(APPEND unsupported_execution_tests exec-split.test) list( APPEND execution_tests @@ -64,6 +64,7 @@ list( exec-snd-expos.test exec-snd-transform.test exec-spawn.test + exec-spawn-future.test exec-starts-on.test exec-stop-when.test exec-stopped-err.test diff --git a/tests/beman/execution/exec-fwd-env.test.cpp b/tests/beman/execution/exec-fwd-env.test.cpp index 6d3a5cfd..d0b3012f 100644 --- a/tests/beman/execution/exec-fwd-env.test.cpp +++ b/tests/beman/execution/exec-fwd-env.test.cpp @@ -48,7 +48,7 @@ TEST(exec_fwd_env) { static_assert(noexcept(test_std::forwarding_query(derived()))); static_assert(test_std::forwarding_query(static_query<>())); static_assert(noexcept(test_std::forwarding_query(static_query<>()))); - static_assert(not test_std::forwarding_query(static_query())); + //-dk:TODO verify this fails to compile: static_assert(not test_std::forwarding_query(static_query())); static_assert(noexcept(test_std::forwarding_query(static_query()))); static_assert(not test_std::forwarding_query(static_query())); static_assert(noexcept(test_std::forwarding_query(static_query()))); diff --git a/tests/beman/execution/exec-get-delegation-scheduler.test.cpp b/tests/beman/execution/exec-get-delegation-scheduler.test.cpp index 1be3b151..6cd80bd4 100644 --- a/tests/beman/execution/exec-get-delegation-scheduler.test.cpp +++ b/tests/beman/execution/exec-get-delegation-scheduler.test.cpp @@ -77,7 +77,7 @@ TEST(exec_get_delegation_scheduler) { static_assert(test_std::forwarding_query((test_std::get_delegation_scheduler))); test_get_delegation_scheduler(test_std::env<>{}); - test_get_delegation_scheduler(env{}); + //-dk:TODO verify that this fails to compile test_get_delegation_scheduler(env{}); test_get_delegation_scheduler(env{}); test_get_delegation_scheduler(env{17}); } diff --git a/tests/beman/execution/exec-get-domain.test.cpp b/tests/beman/execution/exec-get-domain.test.cpp index 154c6daa..925bd56f 100644 --- a/tests/beman/execution/exec-get-domain.test.cpp +++ b/tests/beman/execution/exec-get-domain.test.cpp @@ -102,12 +102,12 @@ TEST(exec_get_domain) { test_get_domain(non_const_get_domain{}); // falling back to `default_domain` test_get_domain(non_const_get_domain{}); // falling back to `default_domain` test_get_domain(has_get_domain{42}); - test_get_domain(has_get_domain{42}); + //-dk:TODO verify that this fails to compile test_get_domain(has_get_domain{42}); test_get_domain(has_get_domain{42}); test_get_domain(has_get_domain{42}); test_get_domain(overloaded_get_domain{}); - static_assert(42 == test_std::get_domain(has_get_domain{42}).value); + static_assert(0 == test_std::get_domain(has_get_domain{42}).value); test_get_domain(env_with_scheduler{}); } diff --git a/tests/beman/execution/exec-get-stop-token.test.cpp b/tests/beman/execution/exec-get-stop-token.test.cpp index 661f40d9..e17cab47 100644 --- a/tests/beman/execution/exec-get-stop-token.test.cpp +++ b/tests/beman/execution/exec-get-stop-token.test.cpp @@ -56,7 +56,8 @@ TEST(exec_get_stop_token) { test_get_stop_token(no_get_stop_token()); test_get_stop_token(has_get_stop_token()); - test_get_stop_token(has_get_stop_token()); + //-dk:TODO test this fails to compile: + // test_get_stop_token(has_get_stop_token()); test_get_stop_token(non_const_get_stop_token()); test_get_stop_token(inconsistent_get_stop_token()); diff --git a/tests/beman/execution/exec-opstate.test.cpp b/tests/beman/execution/exec-opstate.test.cpp index 091d6db0..1dbc9138 100644 --- a/tests/beman/execution/exec-opstate.test.cpp +++ b/tests/beman/execution/exec-opstate.test.cpp @@ -45,7 +45,8 @@ TEST(exec_opstate) { test_operation_state(); test_operation_state>(); - test_operation_state>(); + //-dk:TODO verify that this fails to compile test_operation_state>(); test_operation_state>(); test_operation_state>(); test_operation_state&>(); diff --git a/tests/beman/execution/exec-read-env.test.cpp b/tests/beman/execution/exec-read-env.test.cpp index aa26681c..9c769f92 100644 --- a/tests/beman/execution/exec-read-env.test.cpp +++ b/tests/beman/execution/exec-read-env.test.cpp @@ -34,19 +34,29 @@ struct domain { auto operator==(const domain&) const -> bool = default; }; +struct get_test_domain_t { + template + auto operator()(const Env& ev) const noexcept -> domain { + return ev.query(*this); + } +}; +inline constexpr get_test_domain_t get_test_domain{}; + struct env { int value{}; auto query(test_std::get_domain_t) const noexcept -> domain { return {this->value}; } + auto query(get_test_domain_t) const noexcept -> domain { return {this->value}; } }; struct receiver { using receiver_concept = test_std::receiver_tag; int value{}; + int expect{}; bool* called{}; auto set_value(domain d) && noexcept -> void { - ASSERT(d == domain{this->value}); + ASSERT(d == domain{this->expect}); *this->called = true; } auto set_error(auto&&) && noexcept -> void { @@ -59,8 +69,10 @@ struct receiver { auto test_read_env() -> void { static_assert(test_std::receiver); - ASSERT(domain{17} == test_std::get_domain(env{17})); - ASSERT(domain{17} == test_std::get_domain(test_std::get_env(receiver{17}))); + ASSERT(domain{} == test_std::get_domain(env{17})); + ASSERT(domain{} == test_std::get_domain(test_std::get_env(receiver{17, 0}))); + ASSERT(domain{17} == get_test_domain(env{17})); + ASSERT(domain{17} == get_test_domain(test_std::get_env(receiver{17, 0}))); auto sender{test_std::read_env(test_std::get_domain)}; test::use(sender); static_assert(test_std::sender); @@ -72,10 +84,14 @@ auto test_read_env() -> void { decltype(test_std::get_completion_signatures())>); bool called{}; - auto op{test_std::connect(test_std::read_env(test_std::get_domain), receiver{17, &called})}; - test::use(op); + auto op1{test_std::connect(test_std::read_env(test_std::get_domain), receiver{17, 0, &called})}; ASSERT(not called); - test_std::start(op); + test_std::start(op1); + ASSERT(called); + + called = false; + auto op2{test_std::connect(test_std::read_env(get_test_domain), receiver{17, 17, &called})}; + test_std::start(op2); ASSERT(called); } @@ -123,10 +139,10 @@ auto test_read_env_check_types() -> void { test_std::env<>>(); test_std::read_env_t::impls_for::check_types>(); #if 0 - test_std::read_env_t::impls_for::check_types>(); - test_std::read_env_t::impls_for::check_types>(); + test_std::read_env_t::impls_for::check_types>(); + test_std::read_env_t::impls_for::check_types>(); #endif } } // namespace diff --git a/tests/beman/execution/exec-recv.test.cpp b/tests/beman/execution/exec-recv.test.cpp index a5796087..365fa0c7 100644 --- a/tests/beman/execution/exec-recv.test.cpp +++ b/tests/beman/execution/exec-recv.test.cpp @@ -104,7 +104,8 @@ auto test_valid_completions_for_concept() -> void { static_assert(not test_detail::valid_completion_for)->test_std::set_value_t, receiver1>); static_assert(test_detail::valid_completion_for)->test_std::set_error_t, receiver1>); - static_assert(not test_detail::valid_completion_fortest_std::set_error_t, receiver1>); + //-dk:TODO verify that this fails to compile static_assert(not + // test_detail::valid_completion_fortest_std::set_error_t, receiver1>); static_assert(test_detail::valid_completion_fortest_std::set_stopped_t, receiver1>); } diff --git a/tests/beman/execution/exec-set-error.test.cpp b/tests/beman/execution/exec-set-error.test.cpp index 20ae1a8f..5a694828 100644 --- a/tests/beman/execution/exec-set-error.test.cpp +++ b/tests/beman/execution/exec-set-error.test.cpp @@ -50,10 +50,11 @@ void test_callable() { template auto test_noexcept() { - test::throws obj{}; + [[maybe_unused]] test::throws obj{}; static_assert(requires { test_std::set_error(std::declval(), arg()); }); - static_assert(not requires { test_std::set_error(std::declval(), obj); }); - static_assert(not requires { test_std::set_error(std::declval(), arg_throwing()); }); + //-dk:TODO verify this fails to compile static_assert(not requires { test_std::set_error(std::declval(), obj); + //}); -dk:TODO verify this fails to compile static_assert(not requires { test_std::set_error(std::declval(), + // arg_throwing()); }); } } // namespace diff --git a/tests/beman/execution/exec-set-stopped.test.cpp b/tests/beman/execution/exec-set-stopped.test.cpp index 9bbccd64..53671cb0 100644 --- a/tests/beman/execution/exec-set-stopped.test.cpp +++ b/tests/beman/execution/exec-set-stopped.test.cpp @@ -57,7 +57,7 @@ TEST(exec_set_stopped) { static_assert(std::same_as); test_callable(); - test_noexcept(); + //-dk:TODO verify that this fails to compile test_noexcept(); bool called{false}; ASSERT(not called); diff --git a/tests/beman/execution/exec-snd-expos.test.cpp b/tests/beman/execution/exec-snd-expos.test.cpp index dcdde83c..8bfc3e2e 100644 --- a/tests/beman/execution/exec-snd-expos.test.cpp +++ b/tests/beman/execution/exec-snd-expos.test.cpp @@ -71,9 +71,18 @@ struct custom_result { auto operator==(const custom_result&) const -> bool = default; }; +struct get_test_domain_t { + template + auto operator()(const Env& ev) const noexcept -> domain { + return ev.query(*this); + } +}; +inline constexpr get_test_domain_t get_test_domain{}; + struct env { int value{}; auto query(const test_std::get_domain_t&) const noexcept { return domain{value}; } + auto query(const get_test_domain_t&) const noexcept { return domain{value}; } auto query(const non_forwardable_t&) const noexcept { return true; } auto query(const forwardable_t&, int a, int b) const noexcept { return (value + a) * b; } }; @@ -444,7 +453,7 @@ auto test_completion_domain() -> void { } auto test_query_with_default() -> void { - auto result1{test_detail::query_with_default(test_std::get_domain, env{43}, default_domain{74})}; + auto result1{test_detail::query_with_default(get_test_domain, env{43}, default_domain{74})}; static_assert(std::same_as); ASSERT(result1.value == 43); @@ -946,17 +955,17 @@ auto test_product_type() -> void { test::use(i, b, c); #if 0 //-dk:TODO it seems exporting constrained tuple_size/tuple_element doesn't work - struct derived : decltype(prod) {}; - static_assert(3u == std::tuple_size::value); - static_assert(std::same_as::type>); - static_assert(std::same_as::type>); - static_assert(std::same_as::type>); - derived d{1, true, 'c'}; - auto&& [di, db, dc] = d; - assert(di == d.get<0>()); - assert(db == d.get<1>()); - assert(dc == d.get<2>()); - test::use(di, db, dc); + struct derived : decltype(prod) {}; + static_assert(3u == std::tuple_size::value); + static_assert(std::same_as::type>); + static_assert(std::same_as::type>); + static_assert(std::same_as::type>); + derived d{1, true, 'c'}; + auto&& [di, db, dc] = d; + assert(di == d.get<0>()); + assert(db == d.get<1>()); + assert(dc == d.get<2>()); + test::use(di, db, dc); #endif } auto test_connect_all() -> void { @@ -1121,15 +1130,15 @@ auto test_completion_signatures_for() -> void { //-dk:TODO restore test static_assert(not test_std::sender_in); #if 0 - //-dk:TODO restore completion_signatures_for tests or remove completion_signatures for - static_assert(std::same_as< - test_detail::completion_signatures_for>, - completion_signatures_for_sender::empty_env_sigs - >); - static_assert(std::same_as< - test_detail::completion_signatures_for, - completion_signatures_for_sender::env_sigs - >); + //-dk:TODO restore completion_signatures_for tests or remove completion_signatures for + static_assert(std::same_as< + test_detail::completion_signatures_for>, + completion_signatures_for_sender::empty_env_sigs + >); + static_assert(std::same_as< + test_detail::completion_signatures_for, + completion_signatures_for_sender::env_sigs + >); #endif static_assert( not test_detail::valid_completion_signatures); @@ -1217,15 +1226,15 @@ auto test_basic_sender() -> void { static_assert(test_std::dependent_sender); static_assert(test_std::sender_in); #if 0 - //-dk:TODO restore completion_sigatures_for test - static_assert(std::same_as< - basic_sender_tag::sender::completion_signatures, - test_detail::completion_signatures_for - >); - static_assert(std::same_as< - basic_sender_tag::sender::completion_signatures, - test_detail::completion_signatures_for - >); + //-dk:TODO restore completion_sigatures_for test + static_assert(std::same_as< + basic_sender_tag::sender::completion_signatures, + test_detail::completion_signatures_for + >); + static_assert(std::same_as< + basic_sender_tag::sender::completion_signatures, + test_detail::completion_signatures_for + >); #endif auto ge{test_std::get_env(bs)}; @@ -1235,19 +1244,19 @@ auto test_basic_sender() -> void { auto op{test_std::connect(bs, receiver{})}; test::use(op); #if 0 - static_assert(std::same_as< - basic_sender_tag::sender::completion_signatures, - decltype(bs.get_completion_signatures(env{})) - >); - static_assert(std::same_as< - basic_sender_tag::sender::completion_signatures, - decltype(cbs.get_completion_signatures(env{})) - >); - static_assert(std::same_as< - basic_sender_tag::sender::completion_signatures, - decltype(basic_sender{ basic_sender_tag{}, data{}, sender0 {} } - .get_completion_signatures(env{})) - >); + static_assert(std::same_as< + basic_sender_tag::sender::completion_signatures, + decltype(bs.get_completion_signatures(env{})) + >); + static_assert(std::same_as< + basic_sender_tag::sender::completion_signatures, + decltype(cbs.get_completion_signatures(env{})) + >); + static_assert(std::same_as< + basic_sender_tag::sender::completion_signatures, + decltype(basic_sender{ basic_sender_tag{}, data{}, sender0 {} } + .get_completion_signatures(env{})) + >); #endif static_assert(std::same_as, basic_sender::indices_for>); }