diff --git a/include/beman/execution26/detail/allocator_aware_move.hpp b/include/beman/execution26/detail/allocator_aware_move.hpp index 4bd2b94f..2b77e990 100644 --- a/include/beman/execution26/detail/allocator_aware_move.hpp +++ b/include/beman/execution26/detail/allocator_aware_move.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -20,16 +21,21 @@ template * \internal */ auto allocator_aware_move(T&& obj, Context&& context) noexcept -> decltype(auto) { - if constexpr (requires { ::beman::execution26::get_allocator(::beman::execution26::get_env(context)); }) { - if constexpr (decltype(::beman::execution26::detail::is_product_type(obj))()) { - return obj.make_from(::beman::execution26::get_allocator(::beman::execution26::get_env(context)), - ::std::forward(obj)); + try { + if constexpr (requires { ::beman::execution26::get_allocator(::beman::execution26::get_env(context)); }) { + if constexpr (decltype(::beman::execution26::detail::is_product_type(obj))()) { + return obj.make_from(::beman::execution26::get_allocator(::beman::execution26::get_env(context)), + ::std::forward(obj)); + } else { + return ::std::make_obj_using_allocator( + ::beman::execution26::get_allocator(::beman::execution26::get_env(context)), + ::std::forward(obj)); + } } else { - return ::std::make_obj_using_allocator( - ::beman::execution26::get_allocator(::beman::execution26::get_env(context)), ::std::forward(obj)); + return ::std::forward(obj); } - } else { - return ::std::forward(obj); + } catch (...) { + ::std::terminate(); //-dk:TODO investigate if that can be avoided } } } // namespace beman::execution26::detail diff --git a/include/beman/execution26/detail/product_type.hpp b/include/beman/execution26/detail/product_type.hpp index 0a5783f1..414acff1 100644 --- a/include/beman/execution26/detail/product_type.hpp +++ b/include/beman/execution26/detail/product_type.hpp @@ -48,18 +48,17 @@ struct product_type_base<::std::index_sequence, T...> } template <::std::size_t J> auto get() const& -> decltype(auto) { - return this->element_get(::std::move(*this)); + return this->element_get(*this); } template <::std::size_t J, typename Allocator, typename Self> static auto make_element(Allocator&& alloc, Self&& self) -> decltype(auto) { - using type = ::std::remove_cvref_t(self).template element_get( - std::forward(self)))>; + using type = ::std::remove_cvref_t(std::forward(self)))>; if constexpr (::std::uses_allocator_v) - return ::std::make_obj_using_allocator( - alloc, std::forward(self).template element_get(std::forward(self))); + return ::std::make_obj_using_allocator(alloc, + product_type_base::element_get(std::forward(self))); else - return std::forward(self).template element_get(std::forward(self)); + return product_type_base::element_get(std::forward(self)); } auto operator==(const product_type_base&) const -> bool = default; @@ -69,8 +68,7 @@ template struct product_type : ::beman::execution26::detail::product_type_base<::std::index_sequence_for, T...> { template static auto make_from(Allocator&& allocator, Product&& product, std::index_sequence) -> product_type { - return { - ::std::forward(product).template make_element(allocator, ::std::forward(product))...}; + return {product_type::template make_element(allocator, ::std::forward(product))...}; } template diff --git a/include/beman/execution26/detail/schedule_from.hpp b/include/beman/execution26/detail/schedule_from.hpp index 16f3a22c..50aa66ea 100644 --- a/include/beman/execution26/detail/schedule_from.hpp +++ b/include/beman/execution26/detail/schedule_from.hpp @@ -60,9 +60,8 @@ using as_tuple_t = typename as_tuple::type; struct schedule_from_t { template <::beman::execution26::scheduler Scheduler, ::beman::execution26::sender Sender> auto operator()(Scheduler&& scheduler, Sender&& sender) const { - auto domain{::beman::execution26::detail::query_with_default(::beman::execution26::get_domain, - ::std::forward(scheduler), - ::beman::execution26::default_domain{})}; + auto domain{::beman::execution26::detail::query_with_default( + ::beman::execution26::get_domain, scheduler, ::beman::execution26::default_domain{})}; return ::beman::execution26::transform_sender( domain, ::beman::execution26::detail::make_sender( @@ -78,15 +77,21 @@ struct impls_for<::beman::execution26::detail::schedule_from_t> : ::beman::execu State* state; auto set_value() && noexcept -> void { - ::std::visit( - [this](Tuple& result) noexcept -> void { - if constexpr (not::std::same_as<::std::monostate, Tuple>) { - ::std::apply([this](auto&& tag, - auto&&... args) { tag(std::move(state->receiver), std::move(args)...); }, - result); - } - }, - state->async_result); + try { + ::std::visit( + [this](Tuple& result) noexcept -> void { + if constexpr (not::std::same_as<::std::monostate, Tuple>) { + ::std::apply( + [this](auto&& tag, auto&&... args) { + tag(::std::move(this->state->receiver), ::std::move(args)...); + }, + result); + } + }, + state->async_result); + } catch (...) { + ::beman::execution26::set_error(::std::move(state->receiver), ::std::current_exception()); + } } template diff --git a/include/beman/execution26/detail/when_all.hpp b/include/beman/execution26/detail/when_all.hpp index 2e072265..c8977478 100644 --- a/include/beman/execution26/detail/when_all.hpp +++ b/include/beman/execution26/detail/when_all.hpp @@ -136,13 +136,17 @@ struct impls_for<::beman::execution26::detail::when_all_t> : ::beman::execution2 } break; case disposition::error: this->on_stop.reset(); - ::std::visit( - [&](Error& error) noexcept { - if constexpr (!::std::same_as) { - ::beman::execution26::set_error(::std::move(receiver), ::std::move(error)); - } - }, - this->errors); + try { + ::std::visit( + [&](Error& error) noexcept { + if constexpr (!::std::same_as) { + ::beman::execution26::set_error(::std::move(receiver), ::std::move(error)); + } + }, + this->errors); + } catch (...) { + ::beman::execution26::set_error(::std::move(receiver), ::std::current_exception()); + } break; case disposition::stopped: this->on_stop.reset(); diff --git a/include/beman/execution26/detail/with_await_transform.hpp b/include/beman/execution26/detail/with_await_transform.hpp index c61a427f..8dca2081 100644 --- a/include/beman/execution26/detail/with_await_transform.hpp +++ b/include/beman/execution26/detail/with_await_transform.hpp @@ -11,6 +11,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution26::detail { +// NOLINTBEGIN(bugprone-crtp-constructor-accessibility) template struct with_await_transform { template @@ -24,6 +25,7 @@ struct with_await_transform { return ::std::forward(obj).as_awaitable(static_cast(*this)); } }; +// NOLINTEND(bugprone-crtp-constructor-accessibility) } // namespace beman::execution26::detail // ---------------------------------------------------------------------------- diff --git a/tests/beman/execution26/exec-fwd-env.test.cpp b/tests/beman/execution26/exec-fwd-env.test.cpp index d0ffb666..bc265d52 100644 --- a/tests/beman/execution26/exec-fwd-env.test.cpp +++ b/tests/beman/execution26/exec-fwd-env.test.cpp @@ -52,6 +52,8 @@ TEST(exec_fwd_env) { static_assert(test_std::forwarding_query(dynamic_query())); static_assert(test_std::forwarding_query(dynamic_query{true})); static_assert(not test_std::forwarding_query(dynamic_query{false})); + // NOLINTNEXTLINE(cert-dcl03-c,hicpp-static-assert,misc-static-assert) ASSERT(test_std::forwarding_query(dynamic_query{true})); + // NOLINTNEXTLINE(cert-dcl03-c,hicpp-static-assert,misc-static-assert) ASSERT(not test_std::forwarding_query(dynamic_query{false})); } diff --git a/tests/beman/execution26/exec-general.test.cpp b/tests/beman/execution26/exec-general.test.cpp index 891f652f..a433cd09 100644 --- a/tests/beman/execution26/exec-general.test.cpp +++ b/tests/beman/execution26/exec-general.test.cpp @@ -16,10 +16,17 @@ struct error { struct non_movable { non_movable(non_movable&&) = delete; + non_movable(const non_movable&) = delete; + ~non_movable() = default; + auto operator=(non_movable&&) -> non_movable& = delete; + auto operator=(const non_movable&) -> non_movable& = delete; }; struct non_copyable { non_copyable(non_copyable&&) = default; non_copyable(const non_copyable&) = delete; + ~non_copyable() = default; + auto operator=(non_copyable&&) -> non_copyable& = default; + auto operator=(const non_copyable&) -> non_copyable& = delete; }; auto test_movable_value() -> void { @@ -63,6 +70,7 @@ auto test_as_except_ptr() -> void { } catch (error& e) { ASSERT(e.value == 17); } catch (...) { + // NOLINTNEXTLINE(cert-dcl03-c,hicpp-static-assert,misc-static-assert) ASSERT(nullptr == "wrong exception type produced by as_except_ptr for random error"); } @@ -73,6 +81,7 @@ auto test_as_except_ptr() -> void { } catch (std::system_error& e) { ASSERT(e.code() == errc); } catch (...) { + // NOLINTNEXTLINE(cert-dcl03-c,hicpp-static-assert,misc-static-assert) ASSERT(nullptr == "wrong exception type produced by as_except_ptr for error code"); } } diff --git a/tests/beman/execution26/exec-get-env.test.cpp b/tests/beman/execution26/exec-get-env.test.cpp index f6093249..7f1dd86b 100644 --- a/tests/beman/execution26/exec-get-env.test.cpp +++ b/tests/beman/execution26/exec-get-env.test.cpp @@ -11,10 +11,14 @@ namespace { struct with_non_env; struct non_env { + non_env(non_env&&) = delete; + non_env(const non_env&) = delete; + auto operator=(non_env&&) -> non_env& = delete; + auto operator=(const non_env&) -> non_env& = delete; + private: friend struct with_non_env; - non_env() = default; - non_env(non_env&&) = delete; + non_env() = default; ~non_env() = default; }; struct with_non_env { diff --git a/tests/beman/execution26/exec-just.test.cpp b/tests/beman/execution26/exec-just.test.cpp index e7d635c4..6c2dc4af 100644 --- a/tests/beman/execution26/exec-just.test.cpp +++ b/tests/beman/execution26/exec-just.test.cpp @@ -17,7 +17,11 @@ namespace { struct not_movable { not_movable() = default; + not_movable(const not_movable&) = delete; not_movable(not_movable&&) = delete; + ~not_movable() = default; + auto operator=(const not_movable&) -> not_movable& = delete; + auto operator=(not_movable&&) -> not_movable& = delete; }; template auto test_just_constraints(CPO const& cpo, T&&... args) -> void { @@ -60,7 +64,7 @@ auto test_just_constraints() -> void { template struct value_receiver { using receiver_concept = test_std::receiver_t; - bool* called; + bool* called{}; test_detail::product_type...> expect{}; template @@ -206,7 +210,7 @@ TEST(exec_just) { test_just(); test_just_allocator(); } catch (...) { - ASSERT(nullptr == - "the just tests shouldn't throw"); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) + // NOLINTNEXTLINE(cert-dcl03-c,hicpp-static-assert,misc-static-assert) + ASSERT(nullptr == "the just tests shouldn't throw"); } } diff --git a/tests/beman/execution26/exec-opstate-start.test.cpp b/tests/beman/execution26/exec-opstate-start.test.cpp index 84d6211e..e16dac0e 100644 --- a/tests/beman/execution26/exec-opstate-start.test.cpp +++ b/tests/beman/execution26/exec-opstate-start.test.cpp @@ -10,63 +10,68 @@ namespace { struct receiver { - int value{}; + int& value; auto set_value(int value) && noexcept -> void { this->value = value; } }; -struct non_opstate {}; +struct non_opstate { + receiver rcvr; +}; template struct opstate { - receiver* rcvr; - auto start() const noexcept(Noexcept) -> void { test_std::set_value(::std::move(*rcvr), 42); } + receiver rcvr; + auto start() const noexcept(Noexcept) -> void { test_std::set_value(receiver(this->rcvr.value), 42); } }; template auto test_start_argument_type() { - receiver rcvr{}; - State state{&rcvr}; - receiver crcvr{}; - const State cstate{&crcvr}; + int value{}; + State state{receiver{value}}; + int cvalue{}; + const State cstate{receiver{cvalue}}; static_assert(requires { test_std::start(state); }); static_assert(requires { test_std::start(cstate); }); - static_assert(not requires { test_std::start(State(&rcvr)); }); + static_assert(not requires { test_std::start(State(receiver{value})); }); static_assert(not requires { test_std::start(std::move(state)); }); static_assert(not requires { test_std::start(std::move(cstate)); }); } template auto test_start_member() { - State state{}; + int value{}; + State state{receiver{value}}; static_assert(not requires { test_std::start(state); }); - State cstate{}; + const State cstate{receiver{value}}; static_assert(not requires { test_std::start(cstate); }); } template auto test_start_noexcept() { - State state{}; + int value{}; + State state{receiver{value}}; static_assert(noexcept(state)); - State cstate{}; + int cvalue{}; + const State cstate{receiver{cvalue}}; static_assert(noexcept(cstate)); } template auto test_start_call() { - receiver rcvr{}; - State state{&rcvr}; - receiver crcvr{}; - const State cstate{&crcvr}; + int value{}; + State state{receiver{value}}; + int cvalue{}; + const State cstate{receiver{cvalue}}; - ASSERT(rcvr.value == 0); + ASSERT(value == 0); test_std::start(state); - ASSERT(rcvr.value == 42); + ASSERT(value == 42); - ASSERT(crcvr.value == 0); + ASSERT(cvalue == 0); test_std::start(cstate); - ASSERT(crcvr.value == 42); + ASSERT(cvalue == 42); } } // namespace diff --git a/tests/beman/execution26/exec-set-error.test.cpp b/tests/beman/execution26/exec-set-error.test.cpp index c20aa8ec..1247e4a9 100644 --- a/tests/beman/execution26/exec-set-error.test.cpp +++ b/tests/beman/execution26/exec-set-error.test.cpp @@ -14,15 +14,10 @@ struct arg { }; struct arg_throwing {}; -struct throws { - throws() = default; - throws(const throws&) {} -}; - struct receiver { - template - auto set_error(Error&&) noexcept -> void {} - auto set_error(throws) noexcept -> void {} + auto set_error(int) noexcept -> void {} + // NOTLINTNEXTLINE(performance-unnecessary-value-param) + auto set_error(test::throws) noexcept(false) -> void {} auto set_error(arg a) noexcept -> void { ASSERT(a.value == 43); } auto set_error(arg_throwing) -> void {} }; @@ -42,8 +37,9 @@ void test_callable() { template auto test_noexcept() { + test::throws obj{}; static_assert(requires { test_std::set_error(std::declval(), arg()); }); - static_assert(not requires { test_std::set_error(std::declval(), throws()); }); + static_assert(not requires { test_std::set_error(std::declval(), obj); }); static_assert(not requires { test_std::set_error(std::declval(), arg_throwing()); }); } } // namespace diff --git a/tests/beman/execution26/exec-snd-expos.test.cpp b/tests/beman/execution26/exec-snd-expos.test.cpp index 028e5ca2..ee978fd2 100644 --- a/tests/beman/execution26/exec-snd-expos.test.cpp +++ b/tests/beman/execution26/exec-snd-expos.test.cpp @@ -96,11 +96,10 @@ struct tag { }; template -struct operation_state { +struct operation_state : test_detail::immovable { using operation_state_concept = test_std::operation_state_t; int* counter; - operation_state(int* counter) : counter(counter) {} - operation_state(operation_state&&) = delete; + explicit operation_state(int* counter) : counter(counter) {} auto start() & noexcept -> void { ++*counter; } }; @@ -541,34 +540,34 @@ auto test_default_impls_get_state() -> void { auto operator==(const data&) const -> bool = default; }; struct sender0 { - tag t; + tag t{}; data d{1, 2}; }; struct sender1 { - tag t; + tag t{}; data d{1, 2}; - int i1; + int i1{}; }; struct sender2 { - tag t; + tag t{}; data d{1, 2}; - int i1; - int i2; + int i1{}; + int i2{}; }; struct sender3 { - tag t; + tag t{}; data d{1, 2}; - int i1; - int i2; - int i3; + int i1{}; + int i2{}; + int i3{}; }; struct sender4 { - tag t; + tag t{}; data d{1, 2}; - int i1; - int i2; - int i3; - int i4; + int i1{}; + int i2{}; + int i3{}; + int i4{}; }; struct receiver {}; @@ -816,9 +815,12 @@ auto test_completion_tag() -> void { auto test_product_type() -> void { struct nm { int value{}; - nm() = default; - nm(int value) : value(value) {} + explicit nm(int value) : value(value) {} nm(nm&&) = delete; + nm(const nm&) = delete; + ~nm() = default; + auto operator=(nm&&) -> nm& = delete; + auto operator=(const nm&) -> nm& = delete; auto operator==(const nm&) const -> bool = default; }; auto p0{test_detail::product_type{}}; @@ -827,47 +829,46 @@ auto test_product_type() -> void { auto p1{test_detail::product_type{nm(1)}}; static_assert(p1.size() == 1u); - ASSERT(p1.get<0>() == 1); + ASSERT(p1.get<0>() == nm(1)); auto p2{test_detail::product_type{nm(1), nm(2)}}; static_assert(p2.size() == 2u); - ASSERT(p2.get<0>() == 1); - ASSERT(p2.get<1>() == 2); + ASSERT(p2.get<0>() == nm(1)); + ASSERT(p2.get<1>() == nm(2)); auto p3{test_detail::product_type{nm(1), nm(2), nm(3)}}; static_assert(p3.size() == 3u); - ASSERT(p3.get<0>() == 1); - ASSERT(p3.get<1>() == 2); - ASSERT(p3.get<2>() == 3); + ASSERT(p3.get<0>() == nm(1)); + ASSERT(p3.get<1>() == nm(2)); + ASSERT(p3.get<2>() == nm(3)); auto p4{test_detail::product_type{nm(1), nm(2), nm(3), nm(4)}}; static_assert(p4.size() == 4u); - ASSERT(p4.get<0>() == 1); - ASSERT(p4.get<1>() == 2); - ASSERT(p4.get<2>() == 3); - ASSERT(p4.get<3>() == 4); + ASSERT(p4.get<0>() == nm(1)); + ASSERT(p4.get<1>() == nm(2)); + ASSERT(p4.get<2>() == nm(3)); + ASSERT(p4.get<3>() == nm(4)); auto p5{test_detail::product_type{nm(1), nm(2), nm(3), nm(4), nm(5)}}; static_assert(p5.size() == 5u); - ASSERT(p5.get<0>() == 1); - ASSERT(p5.get<1>() == 2); - ASSERT(p5.get<2>() == 3); - ASSERT(p5.get<3>() == 4); - ASSERT(p5.get<4>() == 5); + ASSERT(p5.get<0>() == nm(1)); + ASSERT(p5.get<1>() == nm(2)); + ASSERT(p5.get<2>() == nm(3)); + ASSERT(p5.get<3>() == nm(4)); + ASSERT(p5.get<4>() == nm(5)); } auto test_connect_all() -> void { static_assert(test_std::operation_state>); { - sender0 s{}; - test_detail::basic_state state{std::move(s), receiver{}}; - auto product{test_detail::connect_all(&state, std::move(s), std::index_sequence<>{})}; + test_detail::basic_state state{sender0{}, receiver{}}; + auto product{test_detail::connect_all(&state, sender0{}, std::index_sequence<>{})}; ASSERT(product.size() == 0); test::use(product); } { - const sender0 s{}; - test_detail::basic_state state{std::move(s), receiver{}}; - auto product{test_detail::connect_all(&state, std::move(s), std::index_sequence<>{})}; + using csender0 = const sender0; + test_detail::basic_state state{csender0{}, receiver{}}; + auto product{test_detail::connect_all(&state, csender0{}, std::index_sequence<>{})}; ASSERT(product.size() == 0); test::use(product); } @@ -880,11 +881,12 @@ auto test_connect_all() -> void { test::use(product); } { - const sender1 s{}; + using csender1 = const sender1; + csender1 s{}; static_assert(requires { s.connect(receiver{}); }); static_assert(requires { test_std::connect(s, receiver{}); }); - test_detail::basic_state state{std::move(s), receiver{}}; - auto product{test_detail::connect_all(&state, std::move(s), std::index_sequence<0>{})}; + test_detail::basic_state state{csender1{}, receiver{}}; + auto product{test_detail::connect_all(&state, csender1{}, std::index_sequence<0>{})}; ASSERT(product.size() == 1); test::use(product); } @@ -897,11 +899,12 @@ auto test_connect_all() -> void { test::use(product); } { - const sender2 s{}; + using csender2 = const sender2; + csender2 s{}; static_assert(requires { s.connect(receiver{}); }); static_assert(requires { test_std::connect(s, receiver{}); }); - test_detail::basic_state state{std::move(s), receiver{}}; - auto product{test_detail::connect_all(&state, std::move(s), std::index_sequence<0, 1>{})}; + test_detail::basic_state state{csender2{}, receiver{}}; + auto product{test_detail::connect_all(&state, csender2{}, std::index_sequence<0, 1>{})}; ASSERT(product.size() == 2); test::use(product); } @@ -914,11 +917,12 @@ auto test_connect_all() -> void { test::use(product); } { - const sender3 s{}; + using csender3 = const sender3; + csender3 s{}; static_assert(requires { s.connect(receiver{}); }); static_assert(requires { test_std::connect(s, receiver{}); }); - test_detail::basic_state state{std::move(s), receiver{}}; - auto product{test_detail::connect_all(&state, std::move(s), std::index_sequence<0, 1, 2>{})}; + test_detail::basic_state state{csender3{}, receiver{}}; + auto product{test_detail::connect_all(&state, csender3{}, std::index_sequence<0, 1, 2>{})}; ASSERT(product.size() == 3); test::use(product); } @@ -931,12 +935,12 @@ auto test_connect_all() -> void { test::use(product); } { - const sender4 s{}; + using csender4 = const sender4; + csender4 s{}; static_assert(requires { s.connect(receiver{}); }); static_assert(requires { test_std::connect(s, receiver{}); }); - test_detail::basic_state state{std::move(s), receiver{}}; - const sender4 s1{}; - auto product{test_detail::connect_all(&state, std::move(s1), std::index_sequence<0, 1, 2, 3>{})}; + test_detail::basic_state state{csender4{}, receiver{}}; + auto product{test_detail::connect_all(&state, csender4{}, std::index_sequence<0, 1, 2, 3>{})}; ASSERT(product.size() == 4); test::use(product); } diff --git a/tests/beman/execution26/exec-snd-transform.test.cpp b/tests/beman/execution26/exec-snd-transform.test.cpp index dcf7e418..b8032aac 100644 --- a/tests/beman/execution26/exec-snd-transform.test.cpp +++ b/tests/beman/execution26/exec-snd-transform.test.cpp @@ -76,7 +76,11 @@ auto test_transform_sender(Dom&& dom, Sender&& sndr) { static_assert(Noexcept == noexcept(test_std::transform_sender(dom, std::forward(sndr)))); ASSERT(value == test_std::transform_sender(dom, std::forward(sndr)).value); } +} +template +auto test_transform_sender_env(Dom&& dom, Sender&& sndr) { + auto value{sndr.value}; static_assert(requires { test_std::transform_sender(dom, std::forward(sndr), env{}); }); if constexpr (requires { test_std::transform_sender(dom, std::forward(sndr), env{}); }) { static_assert( @@ -91,10 +95,13 @@ auto test_transform_sender(Dom&& dom, Sender&& sndr) { TEST(exec_snd_transform) { test_transform_sender&&>(empty_domain{}, final_sender{42}); + test_transform_sender_env&&>(empty_domain{}, final_sender{42}); final_sender fs{42}; test_transform_sender&>(empty_domain{}, fs); + test_transform_sender_env&>(empty_domain{}, fs); const final_sender cfs{42}; test_transform_sender&>(empty_domain{}, cfs); + test_transform_sender_env&>(empty_domain{}, cfs); static_assert(std::same_as, test_std::tag_of_t>>); static_assert(std::same_as, test_std::tag_of_t>>); @@ -110,8 +117,11 @@ TEST(exec_snd_transform) { static_assert(std::same_as, decltype(tag<2>{}.transform_sender(sender<2>{{}, 0}, env{}))>); test_transform_sender>(empty_domain{}, sender<1>{{}, 42}); + test_transform_sender_env>(empty_domain{}, sender<1>{{}, 42}); test_transform_sender>(empty_domain{}, sender<2>{{}, 42}); + test_transform_sender_env>(empty_domain{}, sender<2>{{}, 42}); test_transform_sender>(empty_domain{}, sender<5>{{}, 42}); + test_transform_sender_env>(empty_domain{}, sender<5>{{}, 42}); static_assert(std::same_as&&, decltype(special_domain{}.transform_sender(final_sender{}))>); @@ -121,12 +131,19 @@ TEST(exec_snd_transform) { std::same_as, decltype(special_domain{}.transform_sender(sender<1>{{}, 42}))>); static_assert(std::same_as, decltype(special_domain{}.transform_sender(sender<2>{{}, 42}))>); test_transform_sender&&>(special_domain{}, final_sender{42}); + test_transform_sender_env&&>(special_domain{}, final_sender{42}); final_sender fd{42}; test_transform_sender&>(special_domain{}, fd); + test_transform_sender_env&>(special_domain{}, fd); const final_sender cfd{42}; test_transform_sender&>(special_domain{}, cfd); + test_transform_sender_env&>(special_domain{}, cfd); test_transform_sender>(special_domain{}, final_sender{42}); + test_transform_sender_env>(special_domain{}, final_sender{42}); test_transform_sender>(special_domain{}, sender<1>{{}, 42}); + test_transform_sender_env>(special_domain{}, sender<1>{{}, 42}); test_transform_sender>(special_domain{}, sender<2>{{}, 42}); + test_transform_sender_env>(special_domain{}, sender<2>{{}, 42}); test_transform_sender>(special_domain{}, sender<5>{{}, 42}); + test_transform_sender_env>(special_domain{}, sender<5>{{}, 42}); } diff --git a/tests/beman/execution26/exec-sync-wait.test.cpp b/tests/beman/execution26/exec-sync-wait.test.cpp index 2ec92a35..9e85cfb0 100644 --- a/tests/beman/execution26/exec-sync-wait.test.cpp +++ b/tests/beman/execution26/exec-sync-wait.test.cpp @@ -196,22 +196,21 @@ auto test_sync_wait() -> void { ASSERT(value); ASSERT(*value == (std::tuple{arg<0>{7}, arg<1>{11}})); } catch (...) { - ASSERT( - nullptr == - "no exception expected from sync_wait(just(...)"); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) + // NOLINTBEGIN(cert-dcl03-c,hicpp-static-assert,misc-static-assert) + ASSERT(nullptr == "no exception expected from sync_wait(just(...)"); + // NOLINTEND(cert-dcl03-c,hicpp-static-assert,misc-static-assert) } try { auto value{test_std::sync_wait(send_error{17})}; use(value); - ASSERT(nullptr == - "this line should never be reached"); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) + // NOLINTNEXTLINE(cert-dcl03-c,hicpp-static-assert,misc-static-assert) + ASSERT(nullptr == "this line should never be reached"); } catch (const error& e) { ASSERT(e.value == 17); } catch (...) { - // NOLINTBEGIN(cert-dcl03-c,hicpp-static-assert,misc-static-assert) + // NOLINTNEXTLINE(cert-dcl03-c,hicpp-static-assert,misc-static-assert) ASSERT(nullptr == "no exception expected from sync_wait(just(...)"); - // NOLINTEND(cert-dcl03-c,hicpp-static-assert,misc-static-assert) } try { diff --git a/tests/beman/execution26/exec-when-all.test.cpp b/tests/beman/execution26/exec-when-all.test.cpp index 971a54db..0bc0d872 100644 --- a/tests/beman/execution26/exec-when-all.test.cpp +++ b/tests/beman/execution26/exec-when-all.test.cpp @@ -242,6 +242,12 @@ TEST(exec_when_all) { static_assert(std::same_as); static_assert(std::same_as); - test_when_all(); - test_when_all_with_variant(); + try { + + test_when_all(); + test_when_all_with_variant(); + } catch (...) { + // NOLINTNEXTLINE(cert-dcl03-c,hicpp-static-assert,misc-static-assert) + ASSERT(nullptr == "the when_all tests shouldn't throw"); + } } diff --git a/tests/beman/execution26/functional-syn.test.cpp b/tests/beman/execution26/functional-syn.test.cpp index ad557c59..5eea9a0f 100644 --- a/tests/beman/execution26/functional-syn.test.cpp +++ b/tests/beman/execution26/functional-syn.test.cpp @@ -30,8 +30,8 @@ struct throws { throws(throws&&) noexcept(false) {} throws(const throws&) noexcept(false) {} ~throws() {} - auto operator=(throws&&) noexcept(false) -> throws& { return *this; } - auto operator=(const throws&) noexcept(false) -> throws& { return *this; } + auto operator=(throws&&) noexcept(false) -> throws& = default; + auto operator=(const throws&) noexcept(false) -> throws& = default; }; template @@ -40,6 +40,7 @@ struct fun { auto operator()(int) noexcept(Noexcept) -> void {} auto operator()(non_copyable&&) noexcept(Noexcept) -> void {} auto operator()(arg) && noexcept(Noexcept) -> void {} + // NOLINTNEXTLINE(performance-unnecessary-value-param) auto operator()(throws) noexcept(Noexcept) -> void {} }; diff --git a/tests/beman/execution26/include/test/execution.hpp b/tests/beman/execution26/include/test/execution.hpp index 9c795467..aa87ee3d 100644 --- a/tests/beman/execution26/include/test/execution.hpp +++ b/tests/beman/execution26/include/test/execution.hpp @@ -28,6 +28,16 @@ auto check_type(T1&&) { } auto use(auto&&...) noexcept -> void {} + +struct throws { + throws() = default; + throws(throws&&) noexcept(false) = default; + throws(const throws&) noexcept(false) = default; + ~throws() = default; + auto operator=(throws&&) noexcept(false) -> throws& = default; + auto operator=(const throws&) noexcept(false) -> throws& = default; +}; + } // namespace test #endif // INCLUDED_TEST_EXECUTION diff --git a/tests/beman/execution26/include/test/stop_token.hpp b/tests/beman/execution26/include/test/stop_token.hpp index 5d124211..1e427621 100644 --- a/tests/beman/execution26/include/test/stop_token.hpp +++ b/tests/beman/execution26/include/test/stop_token.hpp @@ -26,13 +26,13 @@ namespace test { template <::test_std::stoppable_token Token, ::std::invocable Stop> -auto stop_visible(Token, Stop) -> void; +auto stop_visible(const Token&, Stop) -> void; template <::test_std::stoppable_token Token, ::std::invocable Stop> -auto stop_callback(Token, Stop) -> void; +auto stop_callback(const Token&, Stop) -> void; template <::test_std::stoppable_token Token, ::std::invocable Stop> -auto stop_callback_dtor_deregisters(Token, Stop) -> void; +auto stop_callback_dtor_deregisters(const Token&, Stop) -> void; template <::test_std::stoppable_token Token, ::std::invocable Stop> -auto stop_callback_dtor_other_thread(Token, Stop) -> void; +auto stop_callback_dtor_other_thread(const Token&, Stop) -> void; template <::test_std::stoppable_token Token, ::std::invocable Stop> auto stop_callback_dtor_same_thread(Token, Stop) -> void; @@ -43,7 +43,7 @@ auto stop_source(MakeStopSource) -> void; // ---------------------------------------------------------------------------- template <::test_std::stoppable_token Token, ::std::invocable Stop> -inline auto test::stop_visible(Token token, Stop stop) -> void { +inline auto test::stop_visible(const Token& token, Stop stop) -> void { // Plan: // - Given a stoppable_token and function to request stop on its associated source. // - When setting up a number of copies of the token they all indicate that @@ -65,7 +65,7 @@ inline auto test::stop_visible(Token token, Stop stop) -> void { // ---------------------------------------------------------------------------- template <::test_std::stoppable_token Token, ::std::invocable Stop> -inline auto test::stop_callback(Token token, Stop stop) -> void { +inline auto test::stop_callback(const Token& token, Stop stop) -> void { // Plan: // - Given a stoppable_token and function to request stop on its associated source. // - When registering a callback before and after requesting stop. At that @@ -114,7 +114,7 @@ inline auto test::stop_callback(Token token, Stop stop) -> void { // ---------------------------------------------------------------------------- template <::test_std::stoppable_token Token, ::std::invocable Stop> -auto test::stop_callback_dtor_deregisters(Token token, Stop stop) -> void { +auto test::stop_callback_dtor_deregisters(const Token& token, Stop stop) -> void { // Plan: // - Given a stop token and a function to request stop. // - When registering and deregistering a callback (i.e., constructing @@ -141,7 +141,7 @@ auto test::stop_callback_dtor_deregisters(Token token, Stop stop) -> void { // ---------------------------------------------------------------------------- template <::test_std::stoppable_token Token, ::std::invocable Stop> -inline auto test::stop_callback_dtor_other_thread(Token token, Stop stop) -> void { +inline auto test::stop_callback_dtor_other_thread(const Token& token, Stop stop) -> void { // Plan: // - Given a stop token and a function to request stop. // - When a callback registered with the with a stop token is deregistered diff --git a/tests/beman/execution26/stopsource-cons.test.cpp b/tests/beman/execution26/stopsource-cons.test.cpp index 0d95564b..ab2e759f 100644 --- a/tests/beman/execution26/stopsource-cons.test.cpp +++ b/tests/beman/execution26/stopsource-cons.test.cpp @@ -21,8 +21,8 @@ auto operator delete(void* ptr, ::std::size_t) noexcept -> void { ::std::free(pt TEST(stopsource_cons) { // Reference: [stopsource.cons] p1 - ::test_std::stop_source source; try { + ::test_std::stop_source source; ASSERT(source.stop_possible()); ASSERT((not source.stop_requested())); } catch (...) { diff --git a/tests/beman/execution26/stopsource-general.test.cpp b/tests/beman/execution26/stopsource-general.test.cpp index 26dd25e9..ae4214df 100644 --- a/tests/beman/execution26/stopsource-general.test.cpp +++ b/tests/beman/execution26/stopsource-general.test.cpp @@ -6,22 +6,27 @@ #include TEST(stopsource_general) { - // Reference: [stopsource.general] p1. - test::stop_source([] { return ::test_std::stop_source(); }); - - ::test_std::stop_source source1; - ::test_std::stop_source source2{::test_std::nostopstate}; - static_assert(noexcept(::test_std::stop_source(::test_std::nostopstate_t()))); try { - ASSERT(not source2.stop_possible()); - ASSERT(not source2.stop_requested()); + // Reference: [stopsource.general] p1. + test::stop_source([] { return ::test_std::stop_source(); }); + + ::test_std::stop_source source1; + ::test_std::stop_source source2{::test_std::nostopstate}; + static_assert(noexcept(::test_std::stop_source(::test_std::nostopstate_t()))); + try { + ASSERT(not source2.stop_possible()); + ASSERT(not source2.stop_requested()); + } catch (...) { + // NOLINTNEXTLINE(cert-dcl03-c,hicpp-static-assert,misc-static-assert) + ASSERT(nullptr == "the stop source should not throw"); + } + + static_assert(noexcept(source1.swap(source2))); + static_assert(noexcept(source1.stop_requested())); + static_assert(noexcept(source1.stop_possible())); + static_assert(noexcept(source1.request_stop())); } catch (...) { // NOLINTNEXTLINE(cert-dcl03-c,hicpp-static-assert,misc-static-assert) - ASSERT(nullptr == "the stop source should not throw"); + ASSERT(nullptr == "stop source tests shouldn't throw"); } - - static_assert(noexcept(source1.swap(source2))); - static_assert(noexcept(source1.stop_requested())); - static_assert(noexcept(source1.stop_possible())); - static_assert(noexcept(source1.request_stop())); } diff --git a/tests/beman/execution26/stopsource-mem.test.cpp b/tests/beman/execution26/stopsource-mem.test.cpp index 6f04b261..2974087a 100644 --- a/tests/beman/execution26/stopsource-mem.test.cpp +++ b/tests/beman/execution26/stopsource-mem.test.cpp @@ -123,9 +123,15 @@ auto test_stopsource_request_stop() -> void { } // namespace TEST(stopsource_mem) { - test_stopsource_swap(); - test_stopsource_get_token(); - test_stopsource_stop_possible(); - test_stopsource_stop_requested(); - test_stopsource_request_stop(); + try { + test_stopsource_swap(); + test_stopsource_get_token(); + test_stopsource_stop_possible(); + test_stopsource_stop_requested(); + test_stopsource_request_stop(); + + } catch (...) { + // NOLINTNEXTLINE(cert-dcl03-c,hicpp-static-assert,misc-static-assert) + ASSERT(nullptr == "the stop source tests shouldn't throw"); + } } diff --git a/tests/beman/execution26/stoptoken-concepts.test.cpp b/tests/beman/execution26/stoptoken-concepts.test.cpp index 353df6c3..4c5cfa7d 100644 --- a/tests/beman/execution26/stoptoken-concepts.test.cpp +++ b/tests/beman/execution26/stoptoken-concepts.test.cpp @@ -5,6 +5,7 @@ #include #include "test/execution.hpp" +namespace { namespace detail_stopppable_callback_for { struct NonToken {}; struct TokenNonCtorCallback { @@ -86,7 +87,11 @@ struct token { template struct callback_type {}; + token(token&&) noexcept(CopyNoexcept); token(const token&) noexcept(CopyNoexcept); + ~token(); + auto operator=(token&&) noexcept(CopyNoexcept) -> token&; + auto operator=(const token&) noexcept(CopyNoexcept) -> token&; auto stop_requested() const noexcept(RequestedNoexcept) -> Requested; auto stop_possible() const noexcept(PossibleNoexcept) -> Possible; auto operator==(const token&) const -> bool = default; @@ -96,7 +101,10 @@ struct non_assignable { template struct callback_type {}; + non_assignable(non_assignable&&) noexcept; non_assignable(const non_assignable&) noexcept; + ~non_assignable(); + auto operator=(non_assignable&&) -> non_assignable& = delete; auto operator=(const non_assignable&) -> non_assignable& = delete; auto stop_requested() const noexcept -> bool; auto stop_possible() const noexcept -> bool; @@ -116,6 +124,9 @@ struct non_swappable { struct callback_type {}; non_swappable(const non_swappable&) noexcept = default; + non_swappable(non_swappable&&) noexcept = delete; + ~non_swappable() noexcept = default; + auto operator=(const non_swappable&) noexcept -> non_swappable& = delete; auto operator=(non_swappable&&) noexcept -> non_swappable& = delete; auto stop_requested() const noexcept -> bool; auto stop_possible() const noexcept -> bool; @@ -152,8 +163,12 @@ struct token { template struct callback_type {}; - constexpr token() {} + constexpr token(); + constexpr token(token&&) noexcept; constexpr token(const token&) noexcept(CopyNoexcept); + constexpr ~token(); + constexpr auto operator=(token&&) noexcept -> token&; + constexpr auto operator=(const token&) noexcept(CopyNoexcept) -> token&; auto stop_requested() const noexcept -> bool; static constexpr auto stop_possible() noexcept -> bool { return Possible; } auto operator==(const token&) const -> bool = default; @@ -180,7 +195,12 @@ struct token { template struct callback_type {}; + token() noexcept(IsToken); + token(token&&) noexcept(IsToken); token(const token&) noexcept(IsToken); + ~token(); + auto operator=(token&&) noexcept(IsToken) -> token&; + auto operator=(const token&) noexcept(IsToken) -> token&; auto stop_requested() const noexcept -> bool; auto stop_possible() const noexcept -> bool; auto operator==(const token&) const -> bool = default; @@ -215,6 +235,7 @@ auto test_detail_stoppable_source() -> void { static_assert(not::test_detail::stoppable_source<::stoppable_source::source>); static_assert(not::test_detail::stoppable_source<::stoppable_source::source>); } +} // namespace TEST(stoptoken_concepts) { test_detail_stopppable_callback_for(); diff --git a/tests/beman/execution26/stoptoken-inplace-members.test.cpp b/tests/beman/execution26/stoptoken-inplace-members.test.cpp index 648626a9..941860bf 100644 --- a/tests/beman/execution26/stoptoken-inplace-members.test.cpp +++ b/tests/beman/execution26/stoptoken-inplace-members.test.cpp @@ -3,6 +3,7 @@ #include "test/execution.hpp" +namespace { auto test_inplace_stop_token_swap() -> void { // Plan: // - Given two inplace_stop_token objects which don't compare equal but @@ -69,6 +70,7 @@ auto test_inplace_stop_token_stop_possible() -> void { ASSERT(connected.stop_possible() == true); ASSERT(disconnected.stop_requested() == false); } +} // namespace TEST(stoptoken_inplace_members) { test_inplace_stop_token_swap();