diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 7d03f522..5b093b21 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -6,6 +6,7 @@ list( APPEND EXAMPLES + inspect playground sender-demo when_all-cancel diff --git a/examples/inspect.cpp b/examples/inspect.cpp new file mode 100644 index 00000000..e6fcd470 --- /dev/null +++ b/examples/inspect.cpp @@ -0,0 +1,76 @@ +// examples/inspectc.pp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include "meta.hpp" +#include +#include +#include + +namespace ex = beman::execution; + +// ---------------------------------------------------------------------------- + +namespace { +struct logger_t { + template + struct state { + using operation_state_concept = ex::operation_state_t; + using inner_t = decltype(ex::connect(std::declval(), std::declval())); + + inner_t inner; + std::remove_cvref_t log; + state(Sndr&& s, Rcvr&& r, Log&& l) + : inner(ex::connect(std::forward(s), std::forward(r))), log(std::forward(l)) {} + auto start() & noexcept -> void { + this->log(meta::type(), + ex::get_env(std::declval())))>::name()); + ex::start(this->inner); + } + }; + + template + struct sender { + using sender_concept = ex::sender_t; + + Sndr sndr; + Log log; + + template + auto get_completion_signatures(const Env& env) const noexcept { + return ex::get_completion_signatures(this->sndr, env); + } + + template + auto connect(Receiver&& receiver) && noexcept(noexcept(ex::connect(std::move(this->sndr), + std::forward(receiver)))) { + return state( + std::move(this->sndr), std::forward(receiver), std::move(this->log)); + } + }; + + template + auto operator()(Sndr&& sndr, Log&& log) const { + return sender, std::remove_cvref_t>{std::forward(sndr), + std::forward(log)}; + } +}; + +inline constexpr logger_t logger{}; +} // namespace + +// ---------------------------------------------------------------------------- + +int main() { + auto log = [](std::string_view name) { + return [name](std::string_view msg) { std::cout << name << " message='" << msg << "'\n"; }; + }; + + ex::sync_wait(logger(ex::just(), log("just()"))); + ex::sync_wait(logger(ex::just() | ex::then([]() {}), log("just() | then(...)"))); + ex::sync_wait(logger(ex::just() | ex::then([]() noexcept {}), log("just() | then(...)"))); + ex::sync_wait(logger(ex::just(0, 1), log("just(0, 1)"))); + ex::sync_wait(logger(ex::just(0, 1, 2), log("just(0, 1, 2)"))); + ex::sync_wait(logger(ex::just_error(0), log("just_error(0)")) | ex::upon_error([](auto) {})); + ex::sync_wait(logger(ex::just_stopped(), log("just_stopped()")) | ex::upon_stopped([]() {})); +} diff --git a/examples/intro-1-hello-world.cpp b/examples/intro-1-hello-world.cpp index 7c9102e4..87cb8d70 100644 --- a/examples/intro-1-hello-world.cpp +++ b/examples/intro-1-hello-world.cpp @@ -18,7 +18,7 @@ int main() { ex::when_all( ex::just("hello, "s), ex::just("world"s) - ) | ex::then([](auto s1, auto s2) { return s1 + s2; }) + ) | ex::then([](auto const& s1, auto const& s2) { return s1 + s2; }) ).value_or(std::tuple(""s) ); // clang-format on diff --git a/examples/intro-2-hello-async.cpp b/examples/intro-2-hello-async.cpp index 5451e64f..7809160c 100644 --- a/examples/intro-2-hello-async.cpp +++ b/examples/intro-2-hello-async.cpp @@ -30,7 +30,7 @@ int main() { | ex::then([] { std::cout << ",\n"; return std::string(", "); }), timer.resume_after(2s) | ex::then([] { std::cout << "w\n"; return std::string("world"); }) - ) | ex::then([](auto s1, auto s2, auto s3) { return s1 + s2 + s3; }) + ) | ex::then([](auto const& s1, auto const& s2, auto const& s3) { return s1 + s2 + s3; }) ) ).value_or(std::tuple(std::string(""))); // clang-format on diff --git a/examples/intro-5-consumer.cpp b/examples/intro-5-consumer.cpp index 0be20b5f..1e769423 100644 --- a/examples/intro-5-consumer.cpp +++ b/examples/intro-5-consumer.cpp @@ -7,12 +7,13 @@ #include #include #include +#include namespace ex = ::beman::execution; using namespace std::string_literals; -enum class success { one }; -enum class failure { fail_one }; +enum class success : std::uint8_t { one }; +enum class failure : std::uint8_t { fail_one }; struct expected_to_channel_t { template diff --git a/examples/meta.hpp b/examples/meta.hpp new file mode 100644 index 00000000..96d8d4d6 --- /dev/null +++ b/examples/meta.hpp @@ -0,0 +1,129 @@ +// examples/meta.hpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef INCLUDED_EXAMPLES_META +#define INCLUDED_EXAMPLES_META + +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- + +namespace meta { +// The code in this namespace is a fairly basic way to print types. It can +// almost certainly be done better, in particular using reflection. However, +// that's beside the point of this example. The important part for the +// example is that meta::type::name() yields a string representing the +// type T in some reasonable way +template