Skip to content
Closed
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
4 changes: 3 additions & 1 deletion include/exec/just_from.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,11 @@ namespace experimental::execution

template <class... Ts>
STDEXEC_ATTRIBUTE(always_inline, host, device)
void operator()(Ts &&...ts) const noexcept
auto
operator()(Ts &&...ts) const noexcept -> STDEXEC::completion_signatures<_set_tag_t(Ts...)>
{
_set_tag_t()(static_cast<Rcvr &&>(_rcvr), static_cast<Ts &&>(ts)...);
return {};
}
};

Expand Down
89 changes: 89 additions & 0 deletions test/exec/test_just_from.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

#include <test_common/catch2.hpp>

#include <concepts>

namespace
{
constinit int global_int = 0;
Expand Down Expand Up @@ -93,6 +95,93 @@ namespace
CHECK(c == 44);
}

TEST_CASE("just_from sinks return value completion signatures", "[just_from]")
{
SECTION("no values")
{
auto s = exec::just_from(
[](auto sink) noexcept
{
auto completions = sink();
STATIC_REQUIRE(
std::same_as<decltype(completions), ex::completion_signatures<ex::set_value_t()>>);
return completions;
});
auto op = ex::connect(s, expect_void_receiver{});
ex::start(op);
}

SECTION("multiple values")
{
auto s = exec::just_from(
[](auto sink) noexcept
{
auto completions = sink(42, 3.14);
STATIC_REQUIRE(std::same_as<decltype(completions),
ex::completion_signatures<ex::set_value_t(int, double)>>);
return completions;
});
auto [i, d] = ex::sync_wait(s).value();
CHECK(i == 42);
CHECK(d == 3.14);
}

SECTION("references")
{
int const value = 42;
auto s = exec::just_from(
[&value](auto sink) noexcept
{
auto completions = sink(global_int, value);
STATIC_REQUIRE(
std::same_as<decltype(completions),
ex::completion_signatures<ex::set_value_t(int&, int const &)>>);
return completions;
});
auto op = ex::connect(s, expect_value_receiver{global_int, value});
ex::start(op);
}
}

TEST_CASE("just_from can return its sink result directly", "[just_from]")
{
auto sender = exec::just_from([](auto sink) noexcept { return sink(17); });
auto [value] = ex::sync_wait(sender).value();
CHECK(value == 17);
}

TEST_CASE("just_error_from sinks return error completion signatures", "[just_from]")
{
auto s = exec::just_error_from(
[](auto sink) noexcept
{
auto completions = sink(42);
STATIC_REQUIRE(
std::same_as<decltype(completions), ex::completion_signatures<ex::set_error_t(int)>>);
return completions;
});
::check_err_types<ex::__mset<int>>(s);
int error = 0;
auto op = ex::connect(std::move(s), expect_error_receiver_ex{error});
ex::start(op);
CHECK(error == 42);
}

TEST_CASE("just_stopped_from sinks return stopped completion signatures", "[just_from]")
{
auto s = exec::just_stopped_from(
[](auto sink) noexcept
{
auto completions = sink();
STATIC_REQUIRE(
std::same_as<decltype(completions), ex::completion_signatures<ex::set_stopped_t()>>);
return completions;
});
::check_sends_stopped<true>(s);
s.submit(expect_stopped_receiver{});
std::move(s).submit(expect_stopped_receiver{});
}

TEST_CASE("just_from is conditionally noexcept when storing the callable", "[just_from]")
{
auto nothrow_fn = [](auto sink) noexcept
Expand Down