33#include < test_common/senders.hpp>
44#include < test_common/type_helpers.hpp>
55
6+ #include < type_traits>
7+
68#include " common.cuh"
79#include " nvexec/stream_context.cuh"
810
@@ -12,6 +14,23 @@ using nvexec::is_on_gpu;
1214
1315namespace
1416{
17+ struct move_only_stopped_handler
18+ {
19+ move_only_stopped_handler () = default ;
20+ move_only_stopped_handler (move_only_stopped_handler const &) = delete ;
21+
22+ STDEXEC_ATTRIBUTE (host, device)
23+ move_only_stopped_handler (move_only_stopped_handler &&) = default ;
24+
25+ STDEXEC_ATTRIBUTE (host, device) auto operator ()() const -> int
26+ {
27+ return 42 ;
28+ }
29+ };
30+
31+ static_assert (std::is_trivially_copyable_v<move_only_stopped_handler>);
32+ static_assert (!std::is_copy_constructible_v<move_only_stopped_handler>);
33+
1534 struct move_only_result
1635 {
1736 STDEXEC_ATTRIBUTE (host, device)
@@ -20,7 +39,7 @@ namespace
2039 {}
2140
2241 STDEXEC_ATTRIBUTE (host, device)
23- move_only_result (move_only_result&& other) noexcept
42+ move_only_result (move_only_result && other) noexcept
2443 : value_(other.value_)
2544 {
2645 other.value_ = 0 ;
@@ -83,6 +102,18 @@ namespace
83102 REQUIRE (flags_storage.all_set_once ());
84103 }
85104
105+ TEST_CASE (" nvexec upon_stopped supports move-only function objects" ,
106+ " [cuda][stream][adaptors][upon_stopped]" )
107+ {
108+ nvexec::stream_context stream_ctx{};
109+
110+ auto snd = ex::just_stopped () | ex::continues_on (stream_ctx.get_scheduler ())
111+ | ex::upon_stopped (move_only_stopped_handler{});
112+ auto const [result] = STDEXEC::sync_wait (std::move (snd)).value ();
113+
114+ REQUIRE (result == 42 );
115+ }
116+
86117 TEST_CASE (" nvexec upon_stopped moves its result" , " [cuda][stream][adaptors][upon_stopped]" )
87118 {
88119 nvexec::stream_context stream_ctx{};
0 commit comments