Skip to content

Commit 2f70a71

Browse files
core(basic sender): fix trailing return type
Signed-off-by: romintomasetti <romin.tomasetti@gmail.com>
1 parent 6d7ad68 commit 2f70a71

2 files changed

Lines changed: 114 additions & 1 deletion

File tree

include/stdexec/__detail/__basic_sender.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,8 @@ namespace STDEXEC
164164

165165
static constexpr auto __get_state = //
166166
[]<class _Sender, class _Receiver>(_Sender&& __sndr, _Receiver&& __rcvr) noexcept(
167-
__nothrow_decay_copyable<__data_of<_Sender>>) -> decltype(auto)
167+
__nothrow_decay_copyable<__data_of<_Sender>>)
168+
-> __state<std::remove_cvref_t<_Receiver>, std::remove_cvref_t<__data_of<_Sender>>>
168169
{
169170
return __state{static_cast<_Receiver&&>(__rcvr),
170171
STDEXEC::__get<1>(static_cast<_Sender&&>(__sndr))};

test/stdexec/algos/adaptors/test_write_env.cpp

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <type_traits>
2222
#include <utility>
2323

24+
#include <exec/single_thread_context.hpp>
2425
#include <stdexec/execution.hpp>
2526
#include <test_common/receivers.hpp>
2627

@@ -68,4 +69,115 @@ namespace
6869
receiver<state>{{}, &s});
6970
::STDEXEC::start(op);
7071
}
72+
73+
template <typename IncompleteType, typename Env = STDEXEC::env_of_t<IncompleteType>>
74+
struct ReceiverIncomplete
75+
{
76+
using receiver_concept = STDEXEC::receiver_tag;
77+
78+
IncompleteType* m_ptr;
79+
80+
void set_value() && noexcept
81+
{
82+
STDEXEC::set_value(std::move(m_ptr->rcvr));
83+
}
84+
85+
template <typename Error>
86+
void set_error(Error&& error) && noexcept
87+
{
88+
STDEXEC::set_error(std::move(m_ptr->rcvr), std::forward<Error>(error));
89+
}
90+
91+
[[nodiscard]]
92+
constexpr auto get_env() const noexcept -> Env
93+
{
94+
return STDEXEC::get_env(*m_ptr);
95+
}
96+
};
97+
98+
template <STDEXEC::sender Sndr, STDEXEC::receiver Rcvr>
99+
struct OpStateIncomplete
100+
{
101+
using operation_state_concept = STDEXEC::operation_state_tag;
102+
103+
using rcvr_t = ReceiverIncomplete<OpStateIncomplete, STDEXEC::env_of_t<Rcvr>>;
104+
using inner_opstate_t = STDEXEC::connect_result_t<Sndr, rcvr_t>;
105+
106+
Rcvr rcvr;
107+
inner_opstate_t inner_opstate;
108+
109+
OpStateIncomplete(Sndr&& sndr, Rcvr rcvr_)
110+
: rcvr(std::move(rcvr_))
111+
, inner_opstate(STDEXEC::connect(std::forward<Sndr>(sndr), rcvr_t{this}))
112+
{}
113+
114+
void start() & noexcept
115+
{
116+
STDEXEC::start(inner_opstate);
117+
}
118+
119+
[[nodiscard]]
120+
constexpr auto get_env() const noexcept -> STDEXEC::env_of_t<Rcvr>
121+
{
122+
return STDEXEC::get_env(rcvr);
123+
}
124+
};
125+
126+
template <STDEXEC::sender Sndr>
127+
struct SenderIncomplete
128+
{
129+
using sender_concept = STDEXEC::sender_tag;
130+
131+
template <class Self, class... Env>
132+
static consteval auto get_completion_signatures()
133+
-> STDEXEC::__completion_signatures_of_t<STDEXEC::__copy_cvref_t<Self, Sndr>, Env...>
134+
{
135+
return {};
136+
}
137+
138+
template <STDEXEC::receiver Rcvr>
139+
auto connect(Rcvr rcvr) && -> OpStateIncomplete<Sndr, Rcvr>
140+
{
141+
return {std::forward<Sndr>(sndr), std::move(rcvr)};
142+
}
143+
144+
Sndr sndr;
145+
};
146+
147+
struct incomplete_t
148+
{
149+
constexpr auto operator()() const noexcept
150+
{
151+
return STDEXEC::__closure(*this);
152+
}
153+
154+
template <typename Sndr>
155+
constexpr auto operator()(Sndr&& sndr) const -> SenderIncomplete<Sndr>
156+
{
157+
return {std::forward<Sndr>(sndr)};
158+
}
159+
};
160+
161+
inline constexpr incomplete_t incomplete{};
162+
163+
TEST_CASE("write_env with a receiver pointing to an incomplete operation state",
164+
"[adaptors][write_env]")
165+
{
166+
exec::single_thread_context stc{};
167+
168+
int value = 0;
169+
170+
STDEXEC::sender auto sndr =
171+
STDEXEC::read_env(STDEXEC::get_allocator)
172+
| STDEXEC::then([](auto allocator)
173+
{ static_assert(std::same_as<decltype(allocator), std::allocator<int>>); })
174+
| STDEXEC::continues_on(stc.get_scheduler()) | incomplete()
175+
| STDEXEC::write_env(STDEXEC::prop{STDEXEC::get_allocator, std::allocator<int>{}})
176+
| STDEXEC::then([&value]() { ++value; });
177+
178+
STDEXEC::sync_wait(std::move(sndr));
179+
180+
CHECK(value == 1);
181+
}
182+
71183
} // namespace

0 commit comments

Comments
 (0)