|
22 | 22 | #include "__receivers.hpp" |
23 | 23 |
|
24 | 24 | #include <memory> |
| 25 | +#include <utility> |
25 | 26 |
|
26 | 27 | namespace STDEXEC |
27 | 28 | { |
28 | | - template <class _Rcvr, class _Env = env_of_t<_Rcvr>> |
29 | | - struct __rcvr_ref |
| 29 | + template <class _RcvrPtr, class _Env = env_of_t<decltype(*_RcvrPtr())>> |
| 30 | + struct __pointer_receiver |
30 | 31 | { |
31 | 32 | using receiver_concept = receiver_t; |
32 | 33 |
|
33 | 34 | STDEXEC_ATTRIBUTE(host, device) |
34 | | - constexpr explicit __rcvr_ref(_Rcvr& __rcvr) noexcept |
35 | | - : __rcvr_{std::addressof(__rcvr)} |
| 35 | + constexpr explicit __pointer_receiver(_RcvrPtr __rcvr_ptr) noexcept |
| 36 | + : __rcvr_ptr_{__rcvr_ptr} |
36 | 37 | {} |
37 | 38 |
|
38 | 39 | template <class... _As> |
39 | 40 | STDEXEC_ATTRIBUTE(host, device) |
40 | 41 | constexpr void set_value(_As&&... __as) noexcept |
41 | 42 | { |
42 | | - STDEXEC::set_value(static_cast<_Rcvr&&>(*__rcvr_), static_cast<_As&&>(__as)...); |
| 43 | + STDEXEC::set_value(std::move(*__rcvr_ptr_), static_cast<_As&&>(__as)...); |
43 | 44 | } |
44 | 45 |
|
45 | 46 | template <class _Error> |
46 | 47 | STDEXEC_ATTRIBUTE(host, device) |
47 | 48 | constexpr void set_error(_Error&& __err) noexcept |
48 | 49 | { |
49 | | - STDEXEC::set_error(static_cast<_Rcvr&&>(*__rcvr_), static_cast<_Error&&>(__err)); |
| 50 | + STDEXEC::set_error(std::move(*__rcvr_ptr_), static_cast<_Error&&>(__err)); |
50 | 51 | } |
51 | 52 |
|
52 | | - STDEXEC_ATTRIBUTE(host, device) constexpr void set_stopped() noexcept |
| 53 | + STDEXEC_ATTRIBUTE(host, device) |
| 54 | + constexpr void set_stopped() noexcept |
53 | 55 | { |
54 | | - STDEXEC::set_stopped(static_cast<_Rcvr&&>(*__rcvr_)); |
| 56 | + STDEXEC::set_stopped(std::move(*__rcvr_ptr_)); |
55 | 57 | } |
56 | 58 |
|
57 | 59 | STDEXEC_ATTRIBUTE(nodiscard, host, device) |
58 | 60 | constexpr auto get_env() const noexcept -> _Env |
59 | 61 | { |
60 | | - static_assert(__same_as<_Env, env_of_t<_Rcvr>>, |
| 62 | + static_assert(__same_as<_Env, env_of_t<decltype(*_RcvrPtr())>>, |
61 | 63 | "get_env() must return the same type as env_of_t<_Rcvr>"); |
62 | | - return STDEXEC::get_env(*__rcvr_); |
| 64 | + return STDEXEC::get_env(*__rcvr_ptr_); |
63 | 65 | } |
64 | 66 |
|
65 | 67 | private: |
66 | | - _Rcvr* __rcvr_; |
| 68 | + _RcvrPtr __rcvr_ptr_; |
67 | 69 | }; |
68 | 70 |
|
69 | | - namespace __detail |
| 71 | + template <class _Rcvr, class _Env = env_of_t<_Rcvr>> |
| 72 | + struct __receiver_ref : __pointer_receiver<_Rcvr*, _Env> |
70 | 73 | { |
71 | | - template <class _Rcvr, size_t = sizeof(_Rcvr)> |
72 | | - STDEXEC_ATTRIBUTE(host, device) |
73 | | - constexpr auto __is_type_complete(int) noexcept |
74 | | - { |
75 | | - return true; |
76 | | - } |
77 | | - |
78 | | - template <class _Rcvr> |
79 | 74 | STDEXEC_ATTRIBUTE(host, device) |
80 | | - constexpr auto __is_type_complete(long) noexcept |
81 | | - { |
82 | | - return false; |
83 | | - } |
84 | | - } // namespace __detail |
85 | | - |
86 | | - // The __ref_rcvr function and its helpers are used to avoid wrapping a receiver in a |
87 | | - // __rcvr_ref when that is possible. The logic goes as follows: |
88 | | - |
89 | | - // 1. If the receiver is an instance of __rcvr_ref, return it. |
90 | | - // 2. If the type is incomplete or an operation state, return a __rcvr_ref wrapping the |
91 | | - // receiver. |
92 | | - // 3. If the receiver is nothrow copy constructible, return it. |
93 | | - // 4. Otherwise, return a __rcvr_ref wrapping the receiver. |
94 | | - template <class _Env = void, class _Rcvr> |
95 | | - STDEXEC_ATTRIBUTE(nodiscard, host, device) |
96 | | - constexpr auto __ref_rcvr(_Rcvr& __rcvr) noexcept |
97 | | - { |
98 | | - if constexpr (__same_as<_Env, void>) |
99 | | - { |
100 | | - return STDEXEC::__ref_rcvr<env_of_t<_Rcvr>>(__rcvr); |
101 | | - } |
102 | | - else if constexpr (__is_instance_of<_Rcvr, __rcvr_ref>) |
103 | | - { |
104 | | - return __rcvr; |
105 | | - } |
106 | | - else if constexpr (!__detail::__is_type_complete<_Rcvr>(0)) |
107 | | - { |
108 | | - return __rcvr_ref<_Rcvr, _Env>{__rcvr}; |
109 | | - } |
110 | | - else if constexpr (operation_state<_Rcvr>) |
111 | | - { |
112 | | - return __rcvr_ref<_Rcvr, _Env>{__rcvr}; |
113 | | - } |
114 | | - else if constexpr (__nothrow_constructible_from<_Rcvr, _Rcvr const &>) |
115 | | - { |
116 | | - return const_cast<_Rcvr const &>(__rcvr); |
117 | | - } |
118 | | - else |
119 | | - { |
120 | | - return __rcvr_ref{__rcvr}; |
121 | | - } |
122 | | - STDEXEC_UNREACHABLE(); |
123 | | - } |
124 | | - |
125 | | - template <class _Rcvr, class _Env = env_of_t<_Rcvr>> |
126 | | - using __rcvr_ref_t = decltype(STDEXEC::__ref_rcvr<_Env>(STDEXEC::__declval<_Rcvr&>())); |
| 75 | + constexpr __receiver_ref(_Rcvr& __rcvr) noexcept |
| 76 | + : __pointer_receiver<_Rcvr*, _Env>(std::addressof(__rcvr)) |
| 77 | + {} |
| 78 | + }; |
127 | 79 | } // namespace STDEXEC |
0 commit comments