Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions include/exec/env.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,10 @@ namespace experimental::execution

template <__decays_to<__sender> _Self, class _Receiver>
constexpr STDEXEC_EXPLICIT_THIS_BEGIN(auto connect)(this _Self&& __self, _Receiver __rcvr)
noexcept(std::is_nothrow_move_constructible_v<_Receiver>)
-> __opstate<_Query, __default_t<env_of_t<_Receiver>>, _Receiver>
noexcept(__nothrow_constructible_from<
__opstate<_Query, __default_t<env_of_t<_Receiver>>, _Receiver>,
__default_t<env_of_t<_Receiver>>,
_Receiver>) -> __opstate<_Query, __default_t<env_of_t<_Receiver>>, _Receiver>
{
using __opstate_t = __opstate<_Query, __default_t<env_of_t<_Receiver>>, _Receiver>;
return __opstate_t{static_cast<_Self&&>(__self).__default_,
Expand Down
55 changes: 55 additions & 0 deletions test/exec/test_env.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,51 @@

namespace
{
struct missing_query : STDEXEC::__query<missing_query>
{
using STDEXEC::__query<missing_query>::operator();
};

struct default_move_error
{};

struct throwing_default
{
explicit throwing_default(bool* throw_on_move) noexcept
: throw_on_move_{throw_on_move}
{}

throwing_default(throwing_default const &) noexcept = default;

throwing_default(throwing_default&& other)
: throw_on_move_{other.throw_on_move_}
{
if (*throw_on_move_)
{
throw default_move_error{};
}
}

bool* throw_on_move_;
};

struct read_with_default_receiver
{
using receiver_concept = STDEXEC::receiver_tag;

template <class _Value>
void set_value(_Value&&) noexcept
{}

void set_error(std::exception_ptr) noexcept {}
void set_stopped() noexcept {}

auto get_env() const noexcept -> STDEXEC::env<>
{
return {};
}
};

// Two dummy properties:
constexpr struct Foo
: STDEXEC::__query<Foo>
Expand Down Expand Up @@ -53,4 +98,14 @@ namespace
STATIC_REQUIRE(!std::invocable<Foo, decltype(e4)>);
CHECK(bar(e4) == 43);
}

TEST_CASE("read_with_default connect propagates default move exceptions", "[env]")
{
bool throw_on_move = false;
auto sndr = exec::read_with_default(missing_query{}, throwing_default{&throw_on_move});
throw_on_move = true;

STATIC_REQUIRE_FALSE(noexcept(std::move(sndr).connect(read_with_default_receiver{})));
CHECK_THROWS_AS(std::move(sndr).connect(read_with_default_receiver{}), default_move_error);
}
} // namespace
Loading