Skip to content

Commit 3a5a798

Browse files
core(basic sender): fix trailing return type (#2081)
* core(basic sender): fix trailing return type --------- Signed-off-by: romintomasetti <romin.tomasetti@gmail.com>
1 parent 8f573d1 commit 3a5a798

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,8 @@
2121
#include <type_traits>
2222
#include <utility>
2323

24+
#include <exec/completion_signatures.hpp>
25+
#include <exec/single_thread_context.hpp>
2426
#include <stdexec/execution.hpp>
2527
#include <test_common/receivers.hpp>
2628

@@ -68,4 +70,114 @@ namespace
6870
receiver<state>{{}, &s});
6971
::STDEXEC::start(op);
7072
}
73+
74+
template <class IncompleteType, class Env = STDEXEC::env_of_t<IncompleteType>>
75+
struct ReceiverIncomplete
76+
{
77+
using receiver_concept = STDEXEC::receiver_tag;
78+
79+
IncompleteType* m_ptr;
80+
81+
void set_value() && noexcept
82+
{
83+
STDEXEC::set_value(std::move(m_ptr->rcvr));
84+
}
85+
86+
template <typename Error>
87+
void set_error(Error&& error) && noexcept
88+
{
89+
STDEXEC::set_error(std::move(m_ptr->rcvr), std::forward<Error>(error));
90+
}
91+
92+
[[nodiscard]]
93+
constexpr auto get_env() const noexcept -> Env
94+
{
95+
return STDEXEC::get_env(*m_ptr);
96+
}
97+
};
98+
99+
template <STDEXEC::sender Sndr, STDEXEC::receiver Rcvr>
100+
struct OpStateIncomplete
101+
{
102+
using operation_state_concept = STDEXEC::operation_state_tag;
103+
104+
using rcvr_t = ReceiverIncomplete<OpStateIncomplete, STDEXEC::env_of_t<Rcvr>>;
105+
using inner_opstate_t = STDEXEC::connect_result_t<Sndr, rcvr_t>;
106+
107+
Rcvr rcvr;
108+
inner_opstate_t inner_opstate;
109+
110+
OpStateIncomplete(Sndr&& sndr, Rcvr rcvr_)
111+
: rcvr(std::move(rcvr_))
112+
, inner_opstate(STDEXEC::connect(std::forward<Sndr>(sndr), rcvr_t{this}))
113+
{}
114+
115+
void start() & noexcept
116+
{
117+
STDEXEC::start(inner_opstate);
118+
}
119+
120+
[[nodiscard]]
121+
constexpr auto get_env() const noexcept -> STDEXEC::env_of_t<Rcvr>
122+
{
123+
return STDEXEC::get_env(rcvr);
124+
}
125+
};
126+
127+
template <STDEXEC::sender Sndr>
128+
struct SenderIncomplete
129+
{
130+
using sender_concept = STDEXEC::sender_tag;
131+
132+
template <class Self, class... Env>
133+
static consteval auto get_completion_signatures()
134+
{
135+
return exec::get_child_completion_signatures<Self, Sndr, Env...>();
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)