diff --git a/.codespellignore b/.codespellignore index 2fddd5ed..d7f036c0 100644 --- a/.codespellignore +++ b/.codespellignore @@ -3,3 +3,4 @@ copyable pullrequest snd statics +Claus diff --git a/docs/modules.md b/docs/modules.md new file mode 100644 index 00000000..91736936 --- /dev/null +++ b/docs/modules.md @@ -0,0 +1,389 @@ +# Supporting Modules + +Author: Dietmar Kühl dietmar.kuehl@me.com +Date: 2026-02-05 + +Originally [`beman.execution`](https://github.com/bemanproject/execution) +was implemented with out `module` support. Eventually, `module` +support in all compilers and in [`cmake`](https://cmake.org/) made +it reasonable to add `module` support. This document describes some +of the experiences of the journey adding `module` support for +[`beman.execution`](https://github.com/bemanproject/execution). It is +likely that my attempts on how to support `module`s were misguided and +I'm happy to learn how things can be done properly or better. + +## History of Adding Module Support + +First, let's start describing what I did. The starting point for +that was a working +[`beman.execution`](https://github.com/bemanproject/execution) +implementation which had no `module` support. It had tests and some +examples and the `CMakeLists.txt` built these. The default build +procedure run from the `Makefile` was already set up to use `ninja`. + +Claus Klein had started to land `cmake` support of `module`s. In +particular there were `cmake` rules to detect whether there is a +dependency scanner and whether `import std;` is supported. The +statement from Claus was that using `import std;` would be the +second step - the first step is to actually create a `module` for +[`beman.execution`](https://github.com/bemanproject/execution) +including the standard library headers. + +### Use `export using` + +I had tried to create a `module` right after the Hagenberg meeting +at the end of 2025. Since I was clueless how to go about that I had +asked people who worked on the `module` specification and implemented +the corresponding support in compilers. The recommendation was to +create a `module` file, include all the headers, start the `module`, +and have `export using ;` declarations. That is, something +like this: + +```c++ +module; + +#include + +export module beman.execution; + +namespace beman::execution { + export using ::beman::execution::forwarding_query_t; + // more of these - one for each name to be exported +} +``` + +Creating a file like that was fairly mechanical work and I just did +it. I tried it. There were a bunch of errors which I could work +out easily but eventually I got stuck with inscrutable errors. +Since I never planned to write about the experience I don't recall +what the errors were. When I asked about it the message was that +neither `cmake` nor the compilers are quite there. So I abandoned +this first attempt. + +Time passed and in the beginning of 2026 some `cmake` support for +`module`s was added via a PR to the repository. The code wasn't +ready to use `module` but it seems reasonable to retry. A first +feeble try to get things built using the `export using` approach +again resulted in errors and there were voice stating that this +won't work but `module` support should actually work. The error +messages seemed to imply that I should `export` the declarations +immediately. So I abandoned that particular approach, again. + +### Generate Module Friendly Code: `mk-module.py` + +The attempts up to this point had indicated a few things which +were somewhat misaligned with the way the code in +[`beman.execution`](https://github.com/bemanproject/execution) +is laid out. The code is structured into lots of small _components_ +(loosely based on John Lakos's idea of components in his 1996 version +of "Large-Scale C++"). Each component consists of + + + +Each component's file includes all necessary headers and a component +`A` is said to _directly depend on a component_ `D` if any of `A`'s +files includes `D`'s header. Creating a graph with the components +as nodes and directed edges from each component to all components +it directly depends on results in dependency graph which does not +contain any cycles. Building the code without `module`s just works +fine. + +When trying directly `export` the declarations of names when they +are first declared, it quickly transpired that this doesn't work +due to the structure of `module` files required by contemporary +compilers: + +
    +
  1. + The first 7 characters of a `module` file shall be `module;` + without anything preceding them. [`g++`](https://gcc.gnu.org/) + and [`clang++`](https://llvm.org/) are somewhat relaxed about + this requirement but some compiler is rather strict. This, however, + is at least easily achieved. +
  2. +
  3. + Any `export` of a name has to follow the `module`'s name declaration, + in this case after `export module beman.execution;`. This makes + sense: the compiler needs to know what `module` the names belong to. +
  4. +
  5. + The problem comes with any standard library header included after + this name declaration: that entirely confuses the compilers. That + is, all headers really need to be included before the name + declaration. That is pretty much _not_ how the components in + [`beman.execution`](https://github.com/bemanproject/execution) are + organized. +
  6. +
+ +To still achieve the objective of `export`ing a name when it first +gets declared, the structure needs to be changed. However, the components +are organized in a consistent structure. So the idea is to use this structure +to reorganize the files for `module` builds: + +
    +
  1. + Add an `export` keyword in front of any declaration which should be + `export`ed (well, really a name which can be defined so the headers can + function both when building a `module` and when just using headers; the + implementation uses `BEMAN_EXECUTION_EXPORT`). +
  2. +
  3. + Use a script (named + [`bin/mk-module.py`](https://github.com/bemanproject/execution/blob/main/bin/mk-module.py)) + to create a `module` definition: +
      +
    1. + Start the file with `module;` (and some header stating the + file is generated). +
    2. +
    3. + Create a list of all used standard library headers and put + these right below the files head. +
    4. +
    5. + Add the `module` name declaration. +
    6. +
    7. + Copy the declaration from all the components in correct + dependency order, i.e., each component's declarations is + preceded by the declarations it directly depends on. +
    8. +
    +
  4. +
  5. Profit!
  6. +
+ +Creating the script to write the file was reasonably straight forward +although I spend way too much time making it fancy and include +suitable `#line` directives to find the actual source. Compiling +the resulting still didn't quite work, of course. There was a bunch +of silly errors in the component headers which could be quickly +resolved, though. That wasn't quite as true for the test files, +though (more [rumination on tests](#modules-vs-testing) below): + +- Many tests didn't include all standard library headers they + dependent on. Since the corresponding header were actually included + by a component header things still worked. So, the corresponding + headers needed to be added. +- Instead of `#include ` the tests + now use `import beman.execution;` (well, the test really use + conditional compilation to either use a header or an `import` + statement). Including any standard library header _after_ the + `import` statement again confuses the compiler, i.e., some + reordering in the files was needed: the test files deliberately + included the component's header first (to make sure all needed + headers are included by the component header) but this include + statement is now replaced by the `import` statement. +- The tests actually use some of the implementation-defined entities + which were not meant to be `export`ed. To still have these tests + I ended up `export`ing the necessary implementation-defined names. + That needs to be corrected eventually (assuming that is actually + possible which isn't quite as clear). +- Of course, the tests actually used the various names and it turned + out that quite a few names, e.g., the `operator|`, were missing. + +That worked OK with one compiler. Then I tried a different compiler +and lots of issues emerged: + +- More names needed to be `export`ed for the tests. +- Some things just didn't compile at all and needed to be changed + (I managed to avoid the problems but I haven't quite understood why). +- Symbols were undefined. + +I ended up spending quite a bit of time reshuffling where headers +go, fixing some actual bugs, and working around what looks like +compiler problems. Most of that was, however, fairly mechanical +and eventually I got a `module` declaration working with all major +C++ compilers (using recent versions of each). + +### Retry `export using` + +Using a script to generate a `module` file restructured to better +match the `module` needs did get me a working `module` definition. +However, that shouldn't really be necessary. While fixing various +minor bugs I did fix a few things which looked as if they may have +had an impact when trying to use `export using `. So tried +that approach again and this time it worked, at least, for some of +the compilers. That looked promising! + +One compiler put up a fight, though! I'm using the an exposition-only +`product_type` class template as is described in +[[exec]](https://eel.is/c++draft/exec#snd.expos-17) and I got a +compiler error about using std::get<N>(sender). +After some experimentation I found that `export`ing the `product_type` +template and the relevant `tuple_size` and `tuple_element` +specialization I could resolve this problem, too. + +Once I got past that I encountered a problem which is probably quite +common: following the specification of exposition-only `impls_for` +class template I used lambda functions for the various "overrides". +One compiler complained about undefined symbols about these! Of +course, using lambda functions in a header is problematic because +each instance of a lambda function has a different type, even if +they are spelled identical! So I replaced all of these lambda functions +by `struct`s which only have one member which is an `operator()`. + +With that I also got a working `module` definition. While I'm quite +fond of my generator I prefer this approach! There shouldn't be a +need to rewrite an implementation just to make it a `module`. I +should also get away not needing any macros to insert/remove the +`export` keywords from declarations. Instead, the `export`ed names +are just listed in the module definition file. What is currently +missing is a bit of a clean-up to remove some of the artifacts. +Also, there may be more implementation details exported than is +actually necessary. + +### `import std;` + +Currently, `import std;` is _not_, yet, used. It should be straight +forward to conditionally choose between `import std;` and including +the headers. + +## Changes Needed to Support Modules + +When enabling modules I needed to apply quite a few, mostly +rather simple changes. Some of the necessary changes did take +me a bit to actually discover. Here is broadly what I needed +to change: + +- I had slotted and `import beman.execution;` in where the + the project header(s) were included. Some headers came + before, others came after. It seems that doesn't work: + any header should preceded the `import` statements or + the `module` name declaration. + +- Especially in the tests I hadn't always included all headers + for standard library components which may be potentially + used. However, these are necessary, even if the standard + library component isn't even named and just used. For + example: + + ```c++ + #include + import beman.execution; + namespace ex = beman::execution; + + int main() { + auto[rc] = *ex::sync_wait(ex::just(0)); + return rc; + } + ``` + + Removing `#include ` causes a compilation failure: + `sync_wait` return an `std::optional>` and the + structured binding needs to know about the `std::tuple`. Oddly, + the `std::optional` can be dereferenced. + +- My biggest blocker was the definition of `join_env`: the original + definition used a `requires` clause which checked whether at + least one of two expressions were values. Implementation used + an `if constexpr` to decide whether the first of the two + expression is value and used that and otherwise the other + expression would be used. That is, something like this: + + ```c++ + template + struct join_env { + E1 e1; + E2 e2; + template + requires( + requires(Q q, const E1& e){ q(e); } || + requires(Q q, const E2& e){ q(e); } + ) + auto query(Q q) const noexcept { + if constexpr (requires(Q q, const E1& e){ q(e); }) + return q(this->e1); + else + return q(this->e2); + } + }; + ``` + + However, the compiler insisted in the definition of the function + that neither of the two expressions from the `requires` clause + was valid. Eventually I just turned the `query` into two + overloads, the first requiring that `q(e1)` is valid and the + second requiring that `q(e1)` is not valid but `q(e2)` is valid. + I think it was only one compiler causing this issue. + +## Scanning and Building + +One of the things which seems odd is that each time `beman.execution` +is built, the files are scanned for dependencies. That scanning +often takes longer than the actual build of the respective object +file. Also, since the `module` gets rebuild, all the tests `import`ing +the `module` get built again. When developing with including headers +only the tests which included modified headers (possibly indirectly) +needed to be rebuilt. Since the components and tests were created +in dependency order, that normally meant that only one test needed +to be rebuilt. Only if an already tested component needed to be +changed multiple tests needed to be built. + +The promise of `module`s was that builds get faster. I don't have +objective measurements but it seems the development actually got +slower. While concentrating on fixing a particular component I +often removed all other tests and the examples from the build. + +## Modules vs. Testing + +Testing the `module` components is, yet, another issue! There are +a few issues and I haven't worked out all of them, yet: + +1. There are quite a few classes and functions which are implementation + details. I like to test these. In fact, I normally don't use `private` + member functions because I can't test them. Instead, this functionality + would become `public` members of an implementation class which then + becomes a `private` member of the actual component. The implementation + class can be tested separately. However, anything which isn't `export`ed + isn't accessible from outside the `module`. + + I still want to test that the `module` works, including all the + implementation details. Currently, the implementation details + are tested by just using the headers to get the declarations. + That doesn't seem quite right, though. Maybe the way to is to + have a second `module` for the implementation details, say, + `beman.execution.detail`, and use that to test the implementation + details. + +2. Some tests would benefit from common tools. For example, there could be + a `test::scheduler` which is used to verify that the various scheduling + operations do the right thing. A `test::scheduler` would be defined in + a header and included into each test. Of course, the `test::scheduler` + would need the declarations of some `module` components, e.g., of + `set_value_t` and, thus, use `import beman.execution`. + + That didn't quite occur to me but it _seems_ that may actually work! + An initial test seems to show that the compilers do not get upset about + multiple `import beman.execution` statements. + +## Conclusion + +So far it isn't clear to me whether `module`s do provide a benefit. The +main sticking points are: + +1. I don't known, yet, how to test implementation details without `export`ing + them. +2. The "scan deps" step seems to take quite long. +3. So far I haven't managed to avoid `export`ing some of the implementation + details. However, that _may_ be due to some uses actually requiring them. +4. There is different behavior between different compilers. + +Some of the issues I encountered are likely due to ignorance: probably +all issues can be resolved with a bit of adjusted practices. diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index c68e6e17..cb15a9cd 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -35,7 +35,7 @@ set(EXAMPLES ) if(BEMAN_USE_MODULES) - list(APPEND EXAMPLES modules) # modules.cpp + list(APPEND EXAMPLES modules modules-and-header) endif() foreach(EXAMPLE ${EXAMPLES}) diff --git a/examples/modules-and-header.cpp b/examples/modules-and-header.cpp new file mode 100644 index 00000000..b531140c --- /dev/null +++ b/examples/modules-and-header.cpp @@ -0,0 +1,11 @@ +// examples/modules-and-header.cpp -*-C++-*- +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +import beman.execution; +namespace ex = beman::execution; + +int main() { + auto [rc] = *ex::sync_wait(ex::just(0)); + return rc; +} diff --git a/include/beman/execution/detail/affine_on.hpp b/include/beman/execution/detail/affine_on.hpp index 44078900..d86d0164 100644 --- a/include/beman/execution/detail/affine_on.hpp +++ b/include/beman/execution/detail/affine_on.hpp @@ -134,8 +134,8 @@ namespace beman::execution { * @brief affine_on is a CPO, used to adapt a sender to complete on the scheduler * it got started on which is derived from get_scheduler on the receiver's environment. */ -BEMAN_EXECUTION_EXPORT using affine_on_t = beman::execution::detail::affine_on_t; -BEMAN_EXECUTION_EXPORT inline constexpr affine_on_t affine_on{}; +using affine_on_t = beman::execution::detail::affine_on_t; +inline constexpr affine_on_t affine_on{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/apply_sender.hpp b/include/beman/execution/detail/apply_sender.hpp index 2cc63a66..2c079a5e 100644 --- a/include/beman/execution/detail/apply_sender.hpp +++ b/include/beman/execution/detail/apply_sender.hpp @@ -16,7 +16,7 @@ namespace beman::execution { * \brief Function used to transform a sender and its arguments for a domain. * \headerfile beman/execution/execution.hpp */ -BEMAN_EXECUTION_EXPORT template +template requires requires(Domain domain, Tag tag, Sender&& sender, Args&&... args) { domain.apply_sender(Tag(), ::std::forward(sender), ::std::forward(args)...); } @@ -29,7 +29,7 @@ constexpr auto apply_sender(Domain domain, Tag, Sender&& sender, Args&&... args) * \brief Default function used to transform a second and its arguments. * \headerfile beman/execution/execution.hpp */ -BEMAN_EXECUTION_EXPORT template +template requires(not requires(Domain domain, Tag tag, Sender&& sender, Args&&... args) { domain.apply_sender(Tag(), ::std::forward(sender), ::std::forward(args)...); }) && requires(Tag tag, Sender&& sender, Args&&... args) { diff --git a/include/beman/execution/detail/as_awaitable.hpp b/include/beman/execution/detail/as_awaitable.hpp index c299be5b..68fa058a 100644 --- a/include/beman/execution/detail/as_awaitable.hpp +++ b/include/beman/execution/detail/as_awaitable.hpp @@ -21,7 +21,7 @@ namespace beman::execution { * \brief Turn an entity, e.g., a sender, into an awaitable. * \headerfile beman/execution/execution.hpp */ -BEMAN_EXECUTION_EXPORT struct as_awaitable_t { +struct as_awaitable_t { template auto operator()(Expr&& expr, Promise& promise) const { if constexpr (requires { ::std::forward(expr).as_awaitable(promise); }) { @@ -39,7 +39,7 @@ BEMAN_EXECUTION_EXPORT struct as_awaitable_t { } } }; -BEMAN_EXECUTION_EXPORT inline constexpr ::beman::execution::as_awaitable_t as_awaitable{}; +inline constexpr ::beman::execution::as_awaitable_t as_awaitable{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/associate.hpp b/include/beman/execution/detail/associate.hpp index 33d89713..a9adf72d 100644 --- a/include/beman/execution/detail/associate.hpp +++ b/include/beman/execution/detail/associate.hpp @@ -21,8 +21,8 @@ // ---------------------------------------------------------------------------- namespace beman::execution::detail { -BEMAN_EXECUTION_EXPORT template <::beman::execution::scope_token Token, - ::beman::execution::sender Sender> //-dk:TODO detail export +template <::beman::execution::scope_token Token, + ::beman::execution::sender Sender> //-dk:TODO detail export struct associate_data { using wrap_sender = ::std::remove_cvref_t().wrap(::std::declval()))>; @@ -65,7 +65,7 @@ struct associate_data { Token token; ::std::optional sender; }; -BEMAN_EXECUTION_EXPORT template <::beman::execution::scope_token Token, ::beman::execution::sender Sender> +template <::beman::execution::scope_token Token, ::beman::execution::sender Sender> associate_data(Token, Sender&&) -> associate_data; struct associate_t { @@ -93,10 +93,11 @@ struct impls_for : ::beman::execution::detail::default_impls { typename ::std::remove_cvref_t::wrap_sender, Receiver>> {}; - static constexpr auto get_state = - [](Sender&& sender, Receiver& receiver) noexcept( - ::std::is_nothrow_constructible_v<::std::remove_cvref_t, Sender>&& - get_noexcept<::std::remove_cvref_t, Receiver>::value) { + struct get_state_impl { + template + auto operator()(Sender&& sender, Receiver& receiver) const + noexcept(::std::is_nothrow_constructible_v<::std::remove_cvref_t, Sender> && + get_noexcept<::std::remove_cvref_t, Receiver>::value) { auto [_, data] = ::std::forward(sender); auto dataParts{data.release()}; @@ -143,8 +144,13 @@ struct impls_for : ::beman::execution::detail::default_impls { }; return dataParts ? op_state(::std::move(dataParts->first), ::std::move(dataParts->second), receiver) : op_state(receiver); - }; - static constexpr auto start = [](auto& state, auto&&) noexcept -> void { state.run(); }; + } + }; + static constexpr auto get_state{get_state_impl{}}; + struct start_impl { + auto operator()(auto& state, auto&&) const noexcept -> void { state.run(); } + }; + static constexpr auto start{start_impl{}}; }; template @@ -156,8 +162,8 @@ struct completion_signatures_for_impl< } // namespace beman::execution::detail namespace beman::execution { -BEMAN_EXECUTION_EXPORT using associate_t = ::beman::execution::detail::associate_t; -BEMAN_EXECUTION_EXPORT inline constexpr associate_t associate{}; +using associate_t = ::beman::execution::detail::associate_t; +inline constexpr associate_t associate{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/await_result_type.hpp b/include/beman/execution/detail/await_result_type.hpp index 6de785d1..c5d959c3 100644 --- a/include/beman/execution/detail/await_result_type.hpp +++ b/include/beman/execution/detail/await_result_type.hpp @@ -16,7 +16,7 @@ namespace beman::execution::detail { * \headerfile beman/execution/execution.hpp * \internal */ -BEMAN_EXECUTION_EXPORT template //-dk:TODO detail export +template //-dk:TODO detail export using await_result_type = decltype(::beman::execution::detail::get_awaiter(::std::declval(), ::std::declval()).await_resume()); } // namespace beman::execution::detail diff --git a/include/beman/execution/detail/basic_operation.hpp b/include/beman/execution/detail/basic_operation.hpp index fd6f8d1a..8ba4fdb1 100644 --- a/include/beman/execution/detail/basic_operation.hpp +++ b/include/beman/execution/detail/basic_operation.hpp @@ -26,7 +26,7 @@ namespace beman::execution::detail { * \internal */ //-dk:TODO the export below shouldn't be needed, but MSVC++ seems to require it (2026-02-01) -BEMAN_EXECUTION_EXPORT template //-dk:TODO detail export +template //-dk:TODO detail export requires ::beman::execution::detail:: //-dk:TODO why is the remove_cvref_t needed...? valid_specialization<::beman::execution::detail::state_type, std::remove_cvref_t, Receiver> diff --git a/include/beman/execution/detail/basic_sender.hpp b/include/beman/execution/detail/basic_sender.hpp index a7e1bc92..62bba28a 100644 --- a/include/beman/execution/detail/basic_sender.hpp +++ b/include/beman/execution/detail/basic_sender.hpp @@ -28,8 +28,8 @@ namespace beman::execution::detail { */ template struct basic_sender : ::beman::execution::detail::product_type { - friend struct ::beman::execution::detail::connect_t; - friend struct ::beman::execution::get_completion_signatures_t; + //-dk:TODO friend struct ::beman::execution::detail::connect_t; + //-dk:TODO friend struct ::beman::execution::get_completion_signatures_t; using sender_concept = ::beman::execution::sender_t; using indices_for = ::std::index_sequence_for; @@ -43,7 +43,7 @@ struct basic_sender : ::beman::execution::detail::product_type) auto connect(Receiver receiver) = BEMAN_EXECUTION_DELETE("the passed receiver doesn't model receiver"); - private: + //-dk:TODO private: #if __cpp_explicit_this_parameter < 302110L //-dk:TODO need to figure out how to use explicit this with forwarding template <::beman::execution::receiver Receiver> auto connect(Receiver receiver) & noexcept( diff --git a/include/beman/execution/detail/basic_state.hpp b/include/beman/execution/detail/basic_state.hpp index 5542371b..128fb7a6 100644 --- a/include/beman/execution/detail/basic_state.hpp +++ b/include/beman/execution/detail/basic_state.hpp @@ -21,7 +21,7 @@ namespace beman::execution::detail { * \internal */ //-dk:TODO the export below shouldn't be needed, but MSVC++ seems to require it (2026-02-01) -BEMAN_EXECUTION_EXPORT template //-dk:TODO detail export +template //-dk:TODO detail export struct basic_state { basic_state(Sender&& sender, Receiver&& rcvr) noexcept(true) : receiver(::std::move(rcvr)), diff --git a/include/beman/execution/detail/bulk.hpp b/include/beman/execution/detail/bulk.hpp index d4613a1a..cdcc896d 100644 --- a/include/beman/execution/detail/bulk.hpp +++ b/include/beman/execution/detail/bulk.hpp @@ -57,38 +57,40 @@ struct bulk_t : ::beman::execution::sender_adaptor_closure { template <> struct impls_for : ::beman::execution::detail::default_impls { - static constexpr auto complete = []( - Index, - ::beman::execution::detail::product_type& state, - Rcvr& rcvr, - Tag, - Args&&... args) noexcept -> void - requires(!::std::same_as || std::is_invocable_v) - { - if constexpr (std::same_as) { - auto& [shape, f] = state; - - using s_type = std::remove_cvref_t; - - constexpr bool nothrow = noexcept(f(s_type(shape), args...)); - - try { - [&]() noexcept(nothrow) { - for (decltype(s_type(shape)) i = 0; i < shape; i++) { - f(s_type(i), args...); + struct complete_impl { + template + requires(!::std::same_as || std::is_invocable_v) + auto operator()(Index, + ::beman::execution::detail::product_type& state, + Rcvr& rcvr, + Tag, + Args&&... args) const noexcept -> void { + if constexpr (std::same_as) { + auto& [shape, f] = state; + + using s_type = std::remove_cvref_t; + + constexpr bool nothrow = noexcept(f(s_type(shape), args...)); + + try { + [&]() noexcept(nothrow) { + for (decltype(s_type(shape)) i = 0; i < shape; i++) { + f(s_type(i), args...); + } + Tag()(std::move(rcvr), std::forward(args)...); + }(); + + } catch (...) { + if constexpr (not nothrow) { + ::beman::execution::set_error(std::move(rcvr), std::current_exception()); } - Tag()(std::move(rcvr), std::forward(args)...); - }(); - - } catch (...) { - if constexpr (not nothrow) { - ::beman::execution::set_error(std::move(rcvr), std::current_exception()); } + } else { + Tag()(std::move(rcvr), std::forward(args)...); } - } else { - Tag()(std::move(rcvr), std::forward(args)...); } }; + static constexpr auto complete{complete_impl{}}; }; template @@ -134,8 +136,8 @@ struct completion_signatures_for_impl< namespace beman::execution { -BEMAN_EXECUTION_EXPORT using bulk_t = ::beman::execution::detail::bulk_t; -BEMAN_EXECUTION_EXPORT inline constexpr ::beman::execution::bulk_t bulk{}; +using bulk_t = ::beman::execution::detail::bulk_t; +inline constexpr ::beman::execution::bulk_t bulk{}; } // namespace beman::execution diff --git a/include/beman/execution/detail/common.hpp b/include/beman/execution/detail/common.hpp index 975537a8..055ba2b9 100644 --- a/include/beman/execution/detail/common.hpp +++ b/include/beman/execution/detail/common.hpp @@ -6,10 +6,6 @@ // ---------------------------------------------------------------------------- -#ifndef BEMAN_EXECUTION_EXPORT -#define BEMAN_EXECUTION_EXPORT -#endif - #if defined(disabled__cpp_deleted_function) #define BEMAN_EXECUTION_DELETE(msg) delete (msg) #else diff --git a/include/beman/execution/detail/completion_signatures.hpp b/include/beman/execution/detail/completion_signatures.hpp index a7a8d449..0da03b1d 100644 --- a/include/beman/execution/detail/completion_signatures.hpp +++ b/include/beman/execution/detail/completion_signatures.hpp @@ -21,7 +21,7 @@ namespace beman::execution { * any specializaion are empty. Objects may be created to return them from * functions used for type computations like get_completion_signatures(sender, env). */ -BEMAN_EXECUTION_EXPORT template <::beman::execution::detail::completion_signature...> +template <::beman::execution::detail::completion_signature...> struct completion_signatures {}; } // namespace beman::execution diff --git a/include/beman/execution/detail/completion_signatures_of_t.hpp b/include/beman/execution/detail/completion_signatures_of_t.hpp index 3b6d6748..2336713c 100644 --- a/include/beman/execution/detail/completion_signatures_of_t.hpp +++ b/include/beman/execution/detail/completion_signatures_of_t.hpp @@ -17,7 +17,7 @@ namespace beman::execution { * \brief Alias to access the completion signatures of a sender * \headerfile beman/execution/execution.hpp */ -BEMAN_EXECUTION_EXPORT template > +template > requires ::beman::execution::sender_in using completion_signatures_of_t = ::beman::execution::detail::call_result_t<::beman::execution::get_completion_signatures_t, Sender, Env>; diff --git a/include/beman/execution/detail/connect.hpp b/include/beman/execution/detail/connect.hpp index f4e30b07..d7584bd3 100644 --- a/include/beman/execution/detail/connect.hpp +++ b/include/beman/execution/detail/connect.hpp @@ -22,7 +22,7 @@ namespace beman::execution::detail { * \internal */ //-dk:TODO this seems to needed for MSVC++ (2026-01-30) -BEMAN_EXECUTION_EXPORT struct connect_t { +struct connect_t { private: template static auto make_new_sender(Sender&& sender, Receiver&& receiver) @@ -83,7 +83,7 @@ namespace beman::execution { * \brief Type of the connect customization point object. * \headerfile beman/execution/execution.hpp */ -BEMAN_EXECUTION_EXPORT using connect_t = beman::execution::detail::connect_t; +using connect_t = beman::execution::detail::connect_t; /*! * \brief Customization point object used to connect a sender and a receiver. * \headerfile beman/execution/execution.hpp @@ -92,7 +92,7 @@ BEMAN_EXECUTION_EXPORT using connect_t = beman::execution::detail::connect_t; * `connect(sender, receiver)` returns the result of calling `sender.connect(receiver)`. * The returned object `state` is an `operation_state` object. */ -BEMAN_EXECUTION_EXPORT inline constexpr connect_t connect{}; +inline constexpr connect_t connect{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/connect_all.hpp b/include/beman/execution/detail/connect_all.hpp index 80d5b4c8..ec2d3c6e 100644 --- a/include/beman/execution/detail/connect_all.hpp +++ b/include/beman/execution/detail/connect_all.hpp @@ -123,7 +123,7 @@ struct connect_all_t { * \internal */ //-dk:TODO the export below shouldn't be needed, but MSVC++ seems to require it (2026-02-01) -BEMAN_EXECUTION_EXPORT constexpr connect_all_t connect_all{}; //-dk:TODO detail export +inline constexpr connect_all_t connect_all{}; //-dk:TODO detail export } // namespace beman::execution::detail #include diff --git a/include/beman/execution/detail/connect_result_t.hpp b/include/beman/execution/detail/connect_result_t.hpp index 0d821b68..f41e9f19 100644 --- a/include/beman/execution/detail/connect_result_t.hpp +++ b/include/beman/execution/detail/connect_result_t.hpp @@ -15,7 +15,7 @@ namespace beman::execution { * \brief Type alias to determine the operation state type returned from `connect()`. * \headerfile beman/execution/execution.hpp */ -BEMAN_EXECUTION_EXPORT template +template using connect_result_t = decltype(::beman::execution::connect(::std::declval(), ::std::declval())); } // namespace beman::execution diff --git a/include/beman/execution/detail/continues_on.hpp b/include/beman/execution/detail/continues_on.hpp index 1a53e8cc..bbeba96b 100644 --- a/include/beman/execution/detail/continues_on.hpp +++ b/include/beman/execution/detail/continues_on.hpp @@ -64,11 +64,14 @@ struct continues_on_t { */ template <> struct impls_for<::beman::execution::detail::continues_on_t> : ::beman::execution::detail::default_impls { - static constexpr auto get_attrs{[](const auto& data, const auto& child) noexcept -> decltype(auto) { - return ::beman::execution::detail::join_env( - ::beman::execution::detail::sched_attrs(data), - ::beman::execution::detail::fwd_env(::beman::execution::get_env(child))); - }}; + struct get_attrs_impl { + auto operator()(const auto& data, const auto& child) const noexcept -> decltype(auto) { + return ::beman::execution::detail::join_env( + ::beman::execution::detail::sched_attrs(data), + ::beman::execution::detail::fwd_env(::beman::execution::get_env(child))); + } + }; + static constexpr auto get_attrs{get_attrs_impl{}}; }; /*! @@ -87,12 +90,12 @@ auto get_domain_late(Sender&& sender, Env&&) { #include namespace beman::execution { -BEMAN_EXECUTION_EXPORT using continues_on_t = ::beman::execution::detail::continues_on_t; +using continues_on_t = ::beman::execution::detail::continues_on_t; /*! * \brief Customization point object to create a `continues_on` sender. * \headerfile beman/execution/execution.hpp */ -BEMAN_EXECUTION_EXPORT inline constexpr continues_on_t continues_on{}; +inline constexpr continues_on_t continues_on{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/counting_scope.hpp b/include/beman/execution/detail/counting_scope.hpp index fb1c51d5..413aab92 100644 --- a/include/beman/execution/detail/counting_scope.hpp +++ b/include/beman/execution/detail/counting_scope.hpp @@ -17,7 +17,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT class counting_scope; +class counting_scope; } // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/counting_scope_join.hpp b/include/beman/execution/detail/counting_scope_join.hpp index 2d557692..1bf15008 100644 --- a/include/beman/execution/detail/counting_scope_join.hpp +++ b/include/beman/execution/detail/counting_scope_join.hpp @@ -75,11 +75,19 @@ struct beman::execution::detail::counting_scope_join_t::state : ::beman::executi namespace beman::execution::detail { template <> struct impls_for<::beman::execution::detail::counting_scope_join_t> : ::beman::execution::detail::default_impls { - static constexpr auto get_state = [](auto&& sender, Receiver& receiver) noexcept(false) { - auto [_, self] = sender; - return ::beman::execution::detail::counting_scope_join_t::state(self, receiver); + struct get_state_impl { + + template + auto operator()(auto&& sender, Receiver& receiver) const noexcept(false) { + auto [_, self] = sender; + return ::beman::execution::detail::counting_scope_join_t::state(self, receiver); + } + }; + static constexpr auto get_state{get_state_impl{}}; + struct start_impl { + auto operator()(auto& s, auto&) const noexcept { s.start(); } }; - static constexpr auto start = [](auto& s, auto&) noexcept { s.start(); }; + static constexpr auto start{start_impl{}}; }; } // namespace beman::execution::detail diff --git a/include/beman/execution/detail/default_domain.hpp b/include/beman/execution/detail/default_domain.hpp index bb29e791..bb9c91fc 100644 --- a/include/beman/execution/detail/default_domain.hpp +++ b/include/beman/execution/detail/default_domain.hpp @@ -25,7 +25,7 @@ namespace beman::execution { * tag type of the passed sender. If there is no corresponding member function * no transformation is applied. */ -BEMAN_EXECUTION_EXPORT struct default_domain { +struct default_domain { template <::beman::execution::sender Sender, ::beman::execution::detail::queryable... Env> requires(sizeof...(Env) <= 1) && requires(Sender&& sender, Env&&... env) { ::beman::execution::tag_of_t().transform_sender(::std::forward(sender), diff --git a/include/beman/execution/detail/env.hpp b/include/beman/execution/detail/env.hpp index 9b87229b..383f00b1 100644 --- a/include/beman/execution/detail/env.hpp +++ b/include/beman/execution/detail/env.hpp @@ -37,7 +37,7 @@ struct find_env { // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT template <::beman::execution::detail::queryable... Envs> +template <::beman::execution::detail::queryable... Envs> struct env : ::beman::execution::detail::env_base... { [[no_unique_address]] ::beman::execution::detail::non_assignable na_{}; diff --git a/include/beman/execution/detail/env_of_t.hpp b/include/beman/execution/detail/env_of_t.hpp index 0983b67d..0f3e0f8e 100644 --- a/include/beman/execution/detail/env_of_t.hpp +++ b/include/beman/execution/detail/env_of_t.hpp @@ -15,7 +15,7 @@ namespace beman::execution { * \brief Determine the type of the environment associated with a type * \headerfile beman/execution/execution.hpp */ -BEMAN_EXECUTION_EXPORT template +template using env_of_t = decltype(::beman::execution::get_env(::std::declval())); } // namespace beman::execution diff --git a/include/beman/execution/detail/env_promise.hpp b/include/beman/execution/detail/env_promise.hpp index b8594dad..d12b23ea 100644 --- a/include/beman/execution/detail/env_promise.hpp +++ b/include/beman/execution/detail/env_promise.hpp @@ -16,7 +16,7 @@ namespace beman::execution::detail { * \headerfile beman/execution/execution.hpp * \internal */ -BEMAN_EXECUTION_EXPORT template //-dk:TODO detail export +template //-dk:TODO detail export struct env_promise : ::beman::execution::detail::with_await_transform { auto get_return_object() noexcept -> void; auto initial_suspend() noexcept -> ::std::suspend_always; diff --git a/include/beman/execution/detail/error_types_of_t.hpp b/include/beman/execution/detail/error_types_of_t.hpp index 4464805d..aea141b9 100644 --- a/include/beman/execution/detail/error_types_of_t.hpp +++ b/include/beman/execution/detail/error_types_of_t.hpp @@ -20,9 +20,9 @@ namespace beman::execution { * \brief Type alias to get error types for a sender * \headerfile beman/execution/execution.hpp */ -BEMAN_EXECUTION_EXPORT template , - template class Variant = ::beman::execution::detail::variant_or_empty> +template , + template class Variant = ::beman::execution::detail::variant_or_empty> requires ::beman::execution::sender_in using error_types_of_t = ::beman::execution::detail::gather_signatures<::beman::execution::set_error_t, diff --git a/include/beman/execution/detail/forwarding_query.hpp b/include/beman/execution/detail/forwarding_query.hpp index bad9d974..c71535b9 100644 --- a/include/beman/execution/detail/forwarding_query.hpp +++ b/include/beman/execution/detail/forwarding_query.hpp @@ -37,7 +37,7 @@ namespace beman::execution { * \brief Type of the forwarding_query customization point object * \headerfile beman/execution/execution.hpp */ -BEMAN_EXECUTION_EXPORT using forwarding_query_t = beman::execution::detail::forwarding_query_t; +using forwarding_query_t = beman::execution::detail::forwarding_query_t; /*! * \brief The customization point object to determine whether queries should be forwarded * \headerfile beman/execution/execution.hpp @@ -50,7 +50,7 @@ BEMAN_EXECUTION_EXPORT using forwarding_query_t = beman::execution::detail::forw * * If the type of `q` is derived from `forwarding_query_t`. * * `false` otherwise. */ -BEMAN_EXECUTION_EXPORT inline constexpr forwarding_query_t forwarding_query{}; +inline constexpr forwarding_query_t forwarding_query{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/fwd_env.hpp b/include/beman/execution/detail/fwd_env.hpp index e85eaee4..b71d11ea 100644 --- a/include/beman/execution/detail/fwd_env.hpp +++ b/include/beman/execution/detail/fwd_env.hpp @@ -19,7 +19,7 @@ namespace beman::execution::detail { * \headerfile beman/execution/execution.hpp * \internal */ -BEMAN_EXECUTION_EXPORT template //-dk:TODO detail export +template //-dk:TODO detail export class fwd_env { private: Env env; diff --git a/include/beman/execution/detail/get_allocator.hpp b/include/beman/execution/detail/get_allocator.hpp index dc54c3ac..0ae11ecf 100644 --- a/include/beman/execution/detail/get_allocator.hpp +++ b/include/beman/execution/detail/get_allocator.hpp @@ -15,7 +15,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT struct get_allocator_t { +struct get_allocator_t { template requires(not requires(Object&& object, const get_allocator_t& tag) { ::std::as_const(object).query(tag); }) auto @@ -50,7 +50,7 @@ BEMAN_EXECUTION_EXPORT struct get_allocator_t { constexpr auto query(const ::beman::execution::forwarding_query_t&) const noexcept -> bool { return true; } }; -BEMAN_EXECUTION_EXPORT inline constexpr get_allocator_t get_allocator{}; +inline constexpr get_allocator_t get_allocator{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/get_completion_scheduler.hpp b/include/beman/execution/detail/get_completion_scheduler.hpp index 517169dc..725e474f 100644 --- a/include/beman/execution/detail/get_completion_scheduler.hpp +++ b/include/beman/execution/detail/get_completion_scheduler.hpp @@ -23,7 +23,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT template +template struct get_completion_scheduler_t; template @@ -78,7 +78,7 @@ struct get_completion_scheduler_t : ::beman::execution::forwarding_query_t { } }; -BEMAN_EXECUTION_EXPORT template <::beman::execution::detail::completion_tag Tag> +template <::beman::execution::detail::completion_tag Tag> inline constexpr get_completion_scheduler_t get_completion_scheduler{}; } // namespace beman::execution diff --git a/include/beman/execution/detail/get_completion_signatures.hpp b/include/beman/execution/detail/get_completion_signatures.hpp index 330591f8..a172ec6e 100644 --- a/include/beman/execution/detail/get_completion_signatures.hpp +++ b/include/beman/execution/detail/get_completion_signatures.hpp @@ -20,7 +20,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT struct get_completion_signatures_t { +struct get_completion_signatures_t { private: template static auto get(Sender&& sender, Env&& env) noexcept { @@ -61,7 +61,7 @@ BEMAN_EXECUTION_EXPORT struct get_completion_signatures_t { return this->get(::std::forward(sender), ::std::forward(env)); } }; -BEMAN_EXECUTION_EXPORT inline constexpr get_completion_signatures_t get_completion_signatures{}; +inline constexpr get_completion_signatures_t get_completion_signatures{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/get_delegation_scheduler.hpp b/include/beman/execution/detail/get_delegation_scheduler.hpp index 427d6086..61c21874 100644 --- a/include/beman/execution/detail/get_delegation_scheduler.hpp +++ b/include/beman/execution/detail/get_delegation_scheduler.hpp @@ -12,7 +12,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT struct get_delegation_scheduler_t { +struct get_delegation_scheduler_t { template requires requires(Env&& env, const get_delegation_scheduler_t& g) { { ::std::as_const(env).query(g) } noexcept -> ::beman::execution::scheduler; @@ -23,7 +23,7 @@ BEMAN_EXECUTION_EXPORT struct get_delegation_scheduler_t { constexpr auto query(const ::beman::execution::forwarding_query_t&) const noexcept -> bool { return true; } }; -BEMAN_EXECUTION_EXPORT inline constexpr get_delegation_scheduler_t get_delegation_scheduler{}; +inline constexpr get_delegation_scheduler_t get_delegation_scheduler{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/get_domain.hpp b/include/beman/execution/detail/get_domain.hpp index 58daf7e3..932e1147 100644 --- a/include/beman/execution/detail/get_domain.hpp +++ b/include/beman/execution/detail/get_domain.hpp @@ -13,7 +13,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT struct get_domain_t { +struct get_domain_t { template requires(not requires(Object&& object, const get_domain_t& tag) { ::std::forward(object).query(tag); @@ -37,7 +37,7 @@ BEMAN_EXECUTION_EXPORT struct get_domain_t { constexpr auto query(const ::beman::execution::forwarding_query_t&) const noexcept -> bool { return true; } }; -BEMAN_EXECUTION_EXPORT inline constexpr get_domain_t get_domain{}; +inline constexpr get_domain_t get_domain{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/get_env.hpp b/include/beman/execution/detail/get_env.hpp index 718163df..ab030f53 100644 --- a/include/beman/execution/detail/get_env.hpp +++ b/include/beman/execution/detail/get_env.hpp @@ -13,7 +13,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT struct get_env_t { +struct get_env_t { template requires(not requires(::std::add_const_t<::std::remove_cvref_t>& object) { object.get_env(); } || ::beman::execution::detail::queryable< @@ -31,7 +31,7 @@ BEMAN_EXECUTION_EXPORT struct get_env_t { } }; -BEMAN_EXECUTION_EXPORT inline constexpr get_env_t get_env{}; +inline constexpr get_env_t get_env{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/get_scheduler.hpp b/include/beman/execution/detail/get_scheduler.hpp index 9daac011..3ab03070 100644 --- a/include/beman/execution/detail/get_scheduler.hpp +++ b/include/beman/execution/detail/get_scheduler.hpp @@ -11,7 +11,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT struct get_scheduler_t : ::beman::execution::forwarding_query_t { +struct get_scheduler_t : ::beman::execution::forwarding_query_t { template requires requires(const get_scheduler_t& self, Env&& env) { ::std::as_const(env).query(self); } auto operator()(Env&& env) const noexcept { @@ -24,7 +24,7 @@ BEMAN_EXECUTION_EXPORT struct get_scheduler_t : ::beman::execution::forwarding_q } }; -BEMAN_EXECUTION_EXPORT inline constexpr get_scheduler_t get_scheduler{}; +inline constexpr get_scheduler_t get_scheduler{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/get_stop_token.hpp b/include/beman/execution/detail/get_stop_token.hpp index 45d0278b..b81bc5ea 100644 --- a/include/beman/execution/detail/get_stop_token.hpp +++ b/include/beman/execution/detail/get_stop_token.hpp @@ -18,7 +18,7 @@ template concept decayed_stoppable_token = ::beman::execution::stoppable_token<::std::decay_t>; } namespace beman::execution { -BEMAN_EXECUTION_EXPORT struct get_stop_token_t { +struct get_stop_token_t { template requires requires(Object&& object, const get_stop_token_t& tag) { { ::std::as_const(object).query(tag) } noexcept -> ::beman::execution::detail::decayed_stoppable_token; @@ -35,7 +35,7 @@ BEMAN_EXECUTION_EXPORT struct get_stop_token_t { constexpr auto query(const ::beman::execution::forwarding_query_t&) const noexcept -> bool { return true; } }; -BEMAN_EXECUTION_EXPORT inline constexpr get_stop_token_t get_stop_token{}; +inline constexpr get_stop_token_t get_stop_token{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/indices_for.hpp b/include/beman/execution/detail/indices_for.hpp index 75358276..8c1a12b6 100644 --- a/include/beman/execution/detail/indices_for.hpp +++ b/include/beman/execution/detail/indices_for.hpp @@ -11,7 +11,7 @@ namespace beman::execution::detail { //-dk:TODO the export below shouldn't be needed, but MSVC++ seems to require it (2026-02-01) -BEMAN_EXECUTION_EXPORT template //-dk:TODO detail export +template //-dk:TODO detail export using indices_for = typename ::std::remove_reference_t::indices_for; } // namespace beman::execution::detail diff --git a/include/beman/execution/detail/inplace_stop_source.hpp b/include/beman/execution/detail/inplace_stop_source.hpp index 214f409f..f010dd53 100644 --- a/include/beman/execution/detail/inplace_stop_source.hpp +++ b/include/beman/execution/detail/inplace_stop_source.hpp @@ -15,11 +15,11 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT class inplace_stop_token; -BEMAN_EXECUTION_EXPORT class inplace_stop_source; -BEMAN_EXECUTION_EXPORT template +class inplace_stop_token; +class inplace_stop_source; +template class inplace_stop_callback; -BEMAN_EXECUTION_EXPORT template +template inplace_stop_callback(::beman::execution::inplace_stop_token, CallbackFun) -> inplace_stop_callback; } // namespace beman::execution diff --git a/include/beman/execution/detail/into_variant.hpp b/include/beman/execution/detail/into_variant.hpp index 7905a582..b494a9cb 100644 --- a/include/beman/execution/detail/into_variant.hpp +++ b/include/beman/execution/detail/into_variant.hpp @@ -30,7 +30,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution::detail { -BEMAN_EXECUTION_EXPORT struct into_variant_t { +struct into_variant_t { template <::beman::execution::sender Sender> auto operator()(Sender&& sender) const { auto domain{::beman::execution::detail::get_domain_early(sender)}; @@ -45,30 +45,37 @@ BEMAN_EXECUTION_EXPORT struct into_variant_t { template <> struct impls_for<::beman::execution::detail::into_variant_t> : ::beman::execution::detail::default_impls { - static constexpr auto get_state = [](Sender&&, Receiver&&) noexcept - -> ::std::type_identity<::beman::execution::value_types_of_t<::beman::execution::detail::child_type, - ::beman::execution::env_of_t>> { - return {}; + struct get_state_impl { + template + auto operator()(Sender&&, Receiver&&) const noexcept -> ::std::type_identity< + ::beman::execution::value_types_of_t<::beman::execution::detail::child_type, + ::beman::execution::env_of_t>> { + return {}; + } }; - static constexpr auto complete = []( - auto, State, auto& receiver, Tag, Args&&... args) noexcept -> void { - if constexpr (::std::same_as) { - using variant_type = typename State::type; - using tuple_type = ::beman::execution::detail::decayed_tuple; - try { - if constexpr (sizeof...(Args) == 0u) - ::beman::execution::set_value(::std::move(receiver)); - else - ::beman::execution::set_value(::std::move(receiver), - variant_type(tuple_type{::std::forward(args)...})); - } catch (...) { - ::beman::execution::set_error(::std::move(receiver), ::std::current_exception()); - } + static constexpr auto get_state{get_state_impl{}}; + struct complete_impl { + template + auto operator()(auto, State, auto& receiver, Tag, Args&&... args) const noexcept -> void { + if constexpr (::std::same_as) { + using variant_type = typename State::type; + using tuple_type = ::beman::execution::detail::decayed_tuple; + try { + if constexpr (sizeof...(Args) == 0u) + ::beman::execution::set_value(::std::move(receiver)); + else + ::beman::execution::set_value(::std::move(receiver), + variant_type(tuple_type{::std::forward(args)...})); + } catch (...) { + ::beman::execution::set_error(::std::move(receiver), ::std::current_exception()); + } - } else { - Tag()(::std::move(receiver), ::std::forward(args)...); + } else { + Tag()(::std::move(receiver), ::std::forward(args)...); + } } }; + static constexpr auto complete{complete_impl{}}; }; template @@ -94,8 +101,8 @@ struct completion_signatures_for_impl< } // namespace beman::execution::detail namespace beman::execution { -BEMAN_EXECUTION_EXPORT using into_variant_t = ::beman::execution::detail::into_variant_t; -BEMAN_EXECUTION_EXPORT inline constexpr into_variant_t into_variant{}; +using into_variant_t = ::beman::execution::detail::into_variant_t; +inline constexpr into_variant_t into_variant{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/just.hpp b/include/beman/execution/detail/just.hpp index 495697a9..9de59bb5 100644 --- a/include/beman/execution/detail/just.hpp +++ b/include/beman/execution/detail/just.hpp @@ -50,20 +50,24 @@ struct completion_signatures_for_impl< template struct impls_for> : ::beman::execution::detail::default_impls { - static constexpr auto start = [](State& state, auto& receiver) noexcept -> void { - [&state, &receiver]<::std::size_t... I>(::std::index_sequence) { - Completion()(::std::move(receiver), ::std::move(state.template get())...); - }(::std::make_index_sequence{}); + struct start_impl { + template + auto operator()(State& state, auto& receiver) const noexcept -> void { + [&state, &receiver]<::std::size_t... I>(::std::index_sequence) { + Completion()(::std::move(receiver), ::std::move(state.template get())...); + }(::std::make_index_sequence{}); + } }; + static constexpr auto start{start_impl{}}; }; } // namespace beman::execution::detail #include namespace beman::execution { -BEMAN_EXECUTION_EXPORT using just_t = ::beman::execution::detail::just_t<::beman::execution::set_value_t>; -BEMAN_EXECUTION_EXPORT using just_error_t = ::beman::execution::detail::just_t<::beman::execution::set_error_t>; -BEMAN_EXECUTION_EXPORT using just_stopped_t = ::beman::execution::detail::just_t<::beman::execution::set_stopped_t>; +using just_t = ::beman::execution::detail::just_t<::beman::execution::set_value_t>; +using just_error_t = ::beman::execution::detail::just_t<::beman::execution::set_error_t>; +using just_stopped_t = ::beman::execution::detail::just_t<::beman::execution::set_stopped_t>; /*! * \brief just(_arg_...) yields a sender completing with set_value_t(_Arg_...) @@ -114,7 +118,7 @@ BEMAN_EXECUTION_EXPORT using just_stopped_t = ::beman::execution::detail::just_t * } * */ -BEMAN_EXECUTION_EXPORT inline constexpr ::beman::execution::just_t just{}; +inline constexpr ::beman::execution::just_t just{}; /*! * \brief just_error(_error_) yields a sender completing with set_error_t(_Error_) @@ -172,7 +176,7 @@ BEMAN_EXECUTION_EXPORT inline constexpr ::beman::execution::just_t just{}; * } * */ -BEMAN_EXECUTION_EXPORT inline constexpr ::beman::execution::just_error_t just_error{}; +inline constexpr ::beman::execution::just_error_t just_error{}; /*! * \brief just_stopped() yields a sender completing with set_stopped_t() @@ -226,7 +230,7 @@ BEMAN_EXECUTION_EXPORT inline constexpr ::beman::execution::just_error_t just_er * } * */ -BEMAN_EXECUTION_EXPORT inline constexpr ::beman::execution::just_stopped_t just_stopped{}; +inline constexpr ::beman::execution::just_stopped_t just_stopped{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/let.hpp b/include/beman/execution/detail/let.hpp index 60448fb7..5d54d54c 100644 --- a/include/beman/execution/detail/let.hpp +++ b/include/beman/execution/detail/let.hpp @@ -179,8 +179,9 @@ struct impls_for<::beman::execution::detail::let_t> : ::beman::execu ::beman::execution::start( state.ops2.template emplace(beman::execution::detail::emplace_from{mkop})); } - static constexpr auto complete{ - [](auto, auto& state, auto& receiver, Tag, Args&&... args) { + struct complete_impl { + template + auto operator()(auto, auto& state, auto& receiver, Tag, Args&&... args) const { if constexpr (::std::same_as) { try { let_bind(state, receiver, ::std::forward(args)...); @@ -191,7 +192,9 @@ struct impls_for<::beman::execution::detail::let_t> : ::beman::execu } else { Tag()(::std::move(receiver), ::std::forward(args)...); } - }}; + } + }; + static constexpr auto complete{complete_impl{}}; }; template @@ -236,13 +239,13 @@ struct completion_signatures_for_impl< #include namespace beman::execution { -BEMAN_EXECUTION_EXPORT using let_error_t = ::beman::execution::detail::let_t<::beman::execution::set_error_t>; -BEMAN_EXECUTION_EXPORT using let_stopped_t = ::beman::execution::detail::let_t<::beman::execution::set_stopped_t>; -BEMAN_EXECUTION_EXPORT using let_value_t = ::beman::execution::detail::let_t<::beman::execution::set_value_t>; +using let_error_t = ::beman::execution::detail::let_t<::beman::execution::set_error_t>; +using let_stopped_t = ::beman::execution::detail::let_t<::beman::execution::set_stopped_t>; +using let_value_t = ::beman::execution::detail::let_t<::beman::execution::set_value_t>; -BEMAN_EXECUTION_EXPORT inline constexpr ::beman::execution::let_error_t let_error{}; -BEMAN_EXECUTION_EXPORT inline constexpr ::beman::execution::let_stopped_t let_stopped{}; -BEMAN_EXECUTION_EXPORT inline constexpr ::beman::execution::let_value_t let_value{}; +inline constexpr ::beman::execution::let_error_t let_error{}; +inline constexpr ::beman::execution::let_stopped_t let_stopped{}; +inline constexpr ::beman::execution::let_value_t let_value{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/make_env.hpp b/include/beman/execution/detail/make_env.hpp index 535e84cc..b93fdd3c 100644 --- a/include/beman/execution/detail/make_env.hpp +++ b/include/beman/execution/detail/make_env.hpp @@ -11,7 +11,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution::detail { -BEMAN_EXECUTION_EXPORT template //-dk:TODO detail export +template //-dk:TODO detail export class make_env { private: Value value; diff --git a/include/beman/execution/detail/never_stop_token.hpp b/include/beman/execution/detail/never_stop_token.hpp index 003f2b17..7329e439 100644 --- a/include/beman/execution/detail/never_stop_token.hpp +++ b/include/beman/execution/detail/never_stop_token.hpp @@ -9,7 +9,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT class never_stop_token; +class never_stop_token; } // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/nostopstate.hpp b/include/beman/execution/detail/nostopstate.hpp index b4763343..aeb5aa0b 100644 --- a/include/beman/execution/detail/nostopstate.hpp +++ b/include/beman/execution/detail/nostopstate.hpp @@ -9,11 +9,11 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT struct nostopstate_t { +struct nostopstate_t { explicit nostopstate_t() = default; }; -BEMAN_EXECUTION_EXPORT inline constexpr nostopstate_t nostopstate{}; +inline constexpr nostopstate_t nostopstate{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/on.hpp b/include/beman/execution/detail/on.hpp index 6038e756..93ed4806 100644 --- a/include/beman/execution/detail/on.hpp +++ b/include/beman/execution/detail/on.hpp @@ -136,8 +136,8 @@ struct on_t : ::beman::execution::sender_adaptor_closure { } // namespace beman::execution::detail namespace beman::execution { -BEMAN_EXECUTION_EXPORT using on_t = ::beman::execution::detail::on_t; -BEMAN_EXECUTION_EXPORT inline constexpr ::beman::execution::on_t on{}; +using on_t = ::beman::execution::detail::on_t; +inline constexpr ::beman::execution::on_t on{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/operation_state.hpp b/include/beman/execution/detail/operation_state.hpp index d1a9a2a8..20d295e8 100644 --- a/include/beman/execution/detail/operation_state.hpp +++ b/include/beman/execution/detail/operation_state.hpp @@ -12,9 +12,9 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT struct operation_state_t {}; +struct operation_state_t {}; -BEMAN_EXECUTION_EXPORT template +template concept operation_state = ::std::derived_from && ::std::is_object_v && requires(State& state) { diff --git a/include/beman/execution/detail/product_type.hpp b/include/beman/execution/detail/product_type.hpp index b3951e61..490dd365 100644 --- a/include/beman/execution/detail/product_type.hpp +++ b/include/beman/execution/detail/product_type.hpp @@ -6,6 +6,7 @@ #include #include +#include #include #include diff --git a/include/beman/execution/detail/prop.hpp b/include/beman/execution/detail/prop.hpp index c5086bec..5fe43e29 100644 --- a/include/beman/execution/detail/prop.hpp +++ b/include/beman/execution/detail/prop.hpp @@ -17,7 +17,7 @@ struct prop_like; } namespace beman::execution { -BEMAN_EXECUTION_EXPORT template +template struct prop; template diff --git a/include/beman/execution/detail/read_env.hpp b/include/beman/execution/detail/read_env.hpp index 020319f6..fceab7c5 100644 --- a/include/beman/execution/detail/read_env.hpp +++ b/include/beman/execution/detail/read_env.hpp @@ -30,14 +30,17 @@ struct read_env_t { template <> struct impls_for<::beman::execution::detail::read_env_t> : ::beman::execution::detail::default_impls { - static constexpr auto start = [](auto query, auto& receiver) noexcept -> void { - try { - auto env{::beman::execution::get_env(receiver)}; - ::beman::execution::set_value(::std::move(receiver), query(env)); - } catch (...) { - ::beman::execution::set_error(::std::move(receiver), ::std::current_exception()); + struct start_impl { + auto operator()(auto query, auto& receiver) const noexcept -> void { + try { + auto env{::beman::execution::get_env(receiver)}; + ::beman::execution::set_value(::std::move(receiver), query(env)); + } catch (...) { + ::beman::execution::set_error(::std::move(receiver), ::std::current_exception()); + } } }; + static constexpr auto start{start_impl{}}; }; template @@ -54,8 +57,8 @@ struct completion_signatures_for_impl< } // namespace beman::execution::detail namespace beman::execution { -BEMAN_EXECUTION_EXPORT using read_env_t = beman::execution::detail::read_env_t; -BEMAN_EXECUTION_EXPORT inline constexpr read_env_t read_env{}; +using read_env_t = beman::execution::detail::read_env_t; +inline constexpr read_env_t read_env{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/receiver.hpp b/include/beman/execution/detail/receiver.hpp index a05ed1ee..ce4a84c9 100644 --- a/include/beman/execution/detail/receiver.hpp +++ b/include/beman/execution/detail/receiver.hpp @@ -13,9 +13,9 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT struct receiver_t {}; +struct receiver_t {}; -BEMAN_EXECUTION_EXPORT template +template concept receiver = ::std::derived_from::receiver_concept, ::beman::execution::receiver_t> && requires(const ::std::remove_cvref_t& rcvr) { diff --git a/include/beman/execution/detail/receiver_of.hpp b/include/beman/execution/detail/receiver_of.hpp index dc0be306..b2901ce9 100644 --- a/include/beman/execution/detail/receiver_of.hpp +++ b/include/beman/execution/detail/receiver_of.hpp @@ -11,7 +11,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT template +template concept receiver_of = beman::execution::receiver && beman::execution::detail::has_completions; } diff --git a/include/beman/execution/detail/run_loop.hpp b/include/beman/execution/detail/run_loop.hpp index 2799ff0f..37a57559 100644 --- a/include/beman/execution/detail/run_loop.hpp +++ b/include/beman/execution/detail/run_loop.hpp @@ -26,7 +26,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT class run_loop { +class run_loop { private: struct scheduler; diff --git a/include/beman/execution/detail/schedule.hpp b/include/beman/execution/detail/schedule.hpp index 25e54591..150596a6 100644 --- a/include/beman/execution/detail/schedule.hpp +++ b/include/beman/execution/detail/schedule.hpp @@ -13,7 +13,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT struct schedule_t { +struct schedule_t { template requires(not requires(Scheduler&& sched) { { ::std::forward(sched).schedule() } -> ::beman::execution::sender; @@ -30,7 +30,7 @@ BEMAN_EXECUTION_EXPORT struct schedule_t { } }; -BEMAN_EXECUTION_EXPORT inline constexpr ::beman::execution::schedule_t schedule{}; +inline constexpr ::beman::execution::schedule_t schedule{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/schedule_from.hpp b/include/beman/execution/detail/schedule_from.hpp index 195b1aab..64de4d2d 100644 --- a/include/beman/execution/detail/schedule_from.hpp +++ b/include/beman/execution/detail/schedule_from.hpp @@ -114,15 +114,20 @@ struct impls_for<::beman::execution::detail::schedule_from_t> : ::beman::executi op_state(::beman::execution::connect(::beman::execution::schedule(sch), receiver_t{this})) {} }; - static constexpr auto get_attrs{[](const auto& data, const auto& child) noexcept -> decltype(auto) { - return ::beman::execution::detail::join_env( - ::beman::execution::detail::sched_attrs(data), - ::beman::execution::detail::fwd_env(::beman::execution::get_env(child))); - }}; - static constexpr auto get_state{ - [](Sender&& sender, Receiver& receiver) //-dk:TODO noexcept(see below) + struct get_attrs_impl { + + auto operator()(const auto& data, const auto& child) const noexcept -> decltype(auto) { + return ::beman::execution::detail::join_env( + ::beman::execution::detail::sched_attrs(data), + ::beman::execution::detail::fwd_env(::beman::execution::get_env(child))); + } + }; + static constexpr auto get_attrs{get_attrs_impl{}}; + struct get_state_impl { + template requires ::beman::execution::sender_in<::beman::execution::detail::child_type, ::beman::execution::env_of_t> + auto operator()(Sender&& sender, Receiver& receiver) const //-dk:TODO noexcept(see below) { auto sch{sender.template get<1>()}; @@ -142,9 +147,12 @@ struct impls_for<::beman::execution::detail::schedule_from_t> : ::beman::executi ::beman::execution::set_stopped_t()>>>>>>; return state_type(sch, receiver); - }}; - static constexpr auto complete{ - [](auto, auto& state, auto& receiver, Tag, Args&&... args) noexcept -> void { + }; + }; + static constexpr auto get_state{get_state_impl{}}; + struct complete_impl { + template + auto operator()(auto, auto& state, auto& receiver, Tag, Args&&... args) const noexcept -> void { using result_t = ::beman::execution::detail::decayed_tuple; constexpr bool nothrow = ::std::is_nothrow_constructible_v; @@ -161,7 +169,9 @@ struct impls_for<::beman::execution::detail::schedule_from_t> : ::beman::executi return; ::beman::execution::start(state.op_state); - }}; + } + }; + static constexpr auto complete{complete_impl{}}; }; template @@ -181,8 +191,8 @@ struct completion_signatures_for_impl< } // namespace beman::execution::detail namespace beman::execution { -BEMAN_EXECUTION_EXPORT using schedule_from_t = beman::execution::detail::schedule_from_t; -BEMAN_EXECUTION_EXPORT inline constexpr ::beman::execution::schedule_from_t schedule_from{}; +using schedule_from_t = beman::execution::detail::schedule_from_t; +inline constexpr ::beman::execution::schedule_from_t schedule_from{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/schedule_result_t.hpp b/include/beman/execution/detail/schedule_result_t.hpp index 1f7b7a88..6b5d26b0 100644 --- a/include/beman/execution/detail/schedule_result_t.hpp +++ b/include/beman/execution/detail/schedule_result_t.hpp @@ -12,7 +12,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT template <::beman::execution::scheduler Scheduler> +template <::beman::execution::scheduler Scheduler> using schedule_result_t = decltype(::beman::execution::schedule(::std::declval())); } diff --git a/include/beman/execution/detail/scheduler.hpp b/include/beman/execution/detail/scheduler.hpp index 71ae0bc8..8dbadbae 100644 --- a/include/beman/execution/detail/scheduler.hpp +++ b/include/beman/execution/detail/scheduler.hpp @@ -17,7 +17,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT template +template concept scheduler = ::beman::execution::detail::almost_scheduler && requires(Scheduler&& sched) { { ::beman::execution::get_completion_scheduler<::beman::execution::set_value_t>( diff --git a/include/beman/execution/detail/scheduler_t.hpp b/include/beman/execution/detail/scheduler_t.hpp index 2765f271..45b415cd 100644 --- a/include/beman/execution/detail/scheduler_t.hpp +++ b/include/beman/execution/detail/scheduler_t.hpp @@ -13,7 +13,7 @@ namespace beman::execution { * \brief Tag type to indicate a class is a scheduler. * \headerfile beman/execution/execution.hpp */ -BEMAN_EXECUTION_EXPORT struct scheduler_t {}; +struct scheduler_t {}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/scope_token.hpp b/include/beman/execution/detail/scope_token.hpp index 1e5b0fe6..7ace3ca3 100644 --- a/include/beman/execution/detail/scope_token.hpp +++ b/include/beman/execution/detail/scope_token.hpp @@ -29,7 +29,7 @@ static_assert(::beman::execution::sender_in<::beman::execution::detail::token_te } // namespace beman::execution::detail namespace beman::execution { -BEMAN_EXECUTION_EXPORT template +template concept scope_token = ::std::copyable && requires(Token token) { { token.try_associate() } -> ::std::same_as; { token.disassociate() } noexcept; diff --git a/include/beman/execution/detail/sender.hpp b/include/beman/execution/detail/sender.hpp index 1633d1fc..746459e8 100644 --- a/include/beman/execution/detail/sender.hpp +++ b/include/beman/execution/detail/sender.hpp @@ -16,7 +16,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT struct sender_t {}; +struct sender_t {}; } // namespace beman::execution namespace beman::execution::detail { template @@ -29,7 +29,7 @@ concept enable_sender = ::beman::execution::detail::env_promise<::beman::execution::env<>>>; } // namespace beman::execution::detail namespace beman::execution { -BEMAN_EXECUTION_EXPORT template +template concept sender = ::beman::execution::detail::enable_sender<::std::remove_cvref_t> && requires(const ::std::remove_cvref_t& sndr) { { ::beman::execution::get_env(sndr) } -> ::beman::execution::detail::queryable; diff --git a/include/beman/execution/detail/sender_adaptor.hpp b/include/beman/execution/detail/sender_adaptor.hpp index a23d3bdc..97f29061 100644 --- a/include/beman/execution/detail/sender_adaptor.hpp +++ b/include/beman/execution/detail/sender_adaptor.hpp @@ -16,7 +16,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution::detail { -BEMAN_EXECUTION_EXPORT template //-dk:TODO detail export +template //-dk:TODO detail export struct sender_adaptor : ::beman::execution::detail::product_type<::std::decay_t, ::std::decay_t...>, ::beman::execution::sender_adaptor_closure> { template <::beman::execution::sender Sender, typename Self> diff --git a/include/beman/execution/detail/sender_adaptor_closure.hpp b/include/beman/execution/detail/sender_adaptor_closure.hpp index 1974093c..1018f4de 100644 --- a/include/beman/execution/detail/sender_adaptor_closure.hpp +++ b/include/beman/execution/detail/sender_adaptor_closure.hpp @@ -18,7 +18,7 @@ struct sender_adaptor_closure_base {}; namespace beman::execution { // NOLINTBEGIN(bugprone-crtp-constructor-accessibility) -BEMAN_EXECUTION_EXPORT template +template struct sender_adaptor_closure : ::beman::execution::detail::pipeable::sender_adaptor_closure_base {}; // NOLINTEND(bugprone-crtp-constructor-accessibility) @@ -31,7 +31,7 @@ concept is_sender_adaptor_closure = } namespace beman::execution::detail::pipeable { -BEMAN_EXECUTION_EXPORT template <::beman::execution::sender Sender, typename Adaptor> +template <::beman::execution::sender Sender, typename Adaptor> requires(!::beman::execution::sender) && ::std::derived_from<::std::decay_t, ::beman::execution::sender_adaptor_closure<::std::decay_t>> && diff --git a/include/beman/execution/detail/sender_in.hpp b/include/beman/execution/detail/sender_in.hpp index b2f2957f..74f158a8 100644 --- a/include/beman/execution/detail/sender_in.hpp +++ b/include/beman/execution/detail/sender_in.hpp @@ -14,7 +14,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT template > +template > concept sender_in = ::beman::execution::sender && ::beman::execution::detail::queryable && requires(Sender&& sender, Env&& env) { diff --git a/include/beman/execution/detail/sends_stopped.hpp b/include/beman/execution/detail/sends_stopped.hpp index 56a0bf82..ae88a299 100644 --- a/include/beman/execution/detail/sends_stopped.hpp +++ b/include/beman/execution/detail/sends_stopped.hpp @@ -16,7 +16,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT template > +template > requires ::beman::execution::sender_in inline constexpr bool sends_stopped{!::std::same_as< ::beman::execution::detail::type_list<>, diff --git a/include/beman/execution/detail/set_error.hpp b/include/beman/execution/detail/set_error.hpp index bd00fc45..9f54268d 100644 --- a/include/beman/execution/detail/set_error.hpp +++ b/include/beman/execution/detail/set_error.hpp @@ -16,7 +16,7 @@ namespace beman::execution { * \brief Type of the customization point object for error completions. * \headerfile beman/execution/execution.hpp */ -BEMAN_EXECUTION_EXPORT struct set_error_t { +struct set_error_t { template auto operator()(Receiver&, Error&&) const -> void = BEMAN_EXECUTION_DELETE("set_error requires the receiver to be passed as non-const rvalue"); @@ -46,7 +46,7 @@ BEMAN_EXECUTION_EXPORT struct set_error_t { * \brief Customization point object for error completions. * \headerfile beman/execution/execution.hpp */ -BEMAN_EXECUTION_EXPORT inline constexpr set_error_t set_error{}; +inline constexpr set_error_t set_error{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/set_stopped.hpp b/include/beman/execution/detail/set_stopped.hpp index 43a68d33..12cc38cc 100644 --- a/include/beman/execution/detail/set_stopped.hpp +++ b/include/beman/execution/detail/set_stopped.hpp @@ -16,7 +16,7 @@ namespace beman::execution { * \brief Type of the customization point object for cancellation completions. * \headerfile beman/execution/execution.hpp */ -BEMAN_EXECUTION_EXPORT struct set_stopped_t { +struct set_stopped_t { template auto operator()(Receiver&) const -> void = BEMAN_EXECUTION_DELETE("set_stopped requires the receiver to be passed as non-const rvalue"); @@ -42,7 +42,7 @@ BEMAN_EXECUTION_EXPORT struct set_stopped_t { * \brief Customization point object for cancellation completions. * \headerfile beman/execution/execution.hpp */ -BEMAN_EXECUTION_EXPORT inline constexpr set_stopped_t set_stopped{}; +inline constexpr set_stopped_t set_stopped{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/set_value.hpp b/include/beman/execution/detail/set_value.hpp index 30dd8bbf..0abd506c 100644 --- a/include/beman/execution/detail/set_value.hpp +++ b/include/beman/execution/detail/set_value.hpp @@ -16,7 +16,7 @@ namespace beman::execution { * \brief Type of the customization point object for successful completions. * \headerfile beman/execution/execution.hpp */ -BEMAN_EXECUTION_EXPORT struct set_value_t { +struct set_value_t { template auto operator()(Receiver&, Args&&...) const -> void = BEMAN_EXECUTION_DELETE("set_value requires the receiver to be passed as non-const rvalue"); @@ -44,7 +44,7 @@ BEMAN_EXECUTION_EXPORT struct set_value_t { * \brief Customization point object for successful completions. * \headerfile beman/execution/execution.hpp */ -BEMAN_EXECUTION_EXPORT inline constexpr set_value_t set_value{}; +inline constexpr set_value_t set_value{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/simple_allocator.hpp b/include/beman/execution/detail/simple_allocator.hpp index eab53f60..ca806273 100644 --- a/include/beman/execution/detail/simple_allocator.hpp +++ b/include/beman/execution/detail/simple_allocator.hpp @@ -11,7 +11,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution::detail { -BEMAN_EXECUTION_EXPORT template //-dk:TODO detail export +template //-dk:TODO detail export concept simple_allocator = requires(::std::remove_cvref_t alloc, ::std::size_t n) { { *alloc.allocate(n) } -> ::std::same_as::value_type&>; diff --git a/include/beman/execution/detail/simple_counting_scope.hpp b/include/beman/execution/detail/simple_counting_scope.hpp index 1a5d1269..ddad87aa 100644 --- a/include/beman/execution/detail/simple_counting_scope.hpp +++ b/include/beman/execution/detail/simple_counting_scope.hpp @@ -14,7 +14,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT class simple_counting_scope; +class simple_counting_scope; } // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/spawn.hpp b/include/beman/execution/detail/spawn.hpp index ae4b6ecc..fd058303 100644 --- a/include/beman/execution/detail/spawn.hpp +++ b/include/beman/execution/detail/spawn.hpp @@ -85,8 +85,8 @@ struct spawn_t { } // namespace beman::execution::detail namespace beman::execution { -BEMAN_EXECUTION_EXPORT using spawn_t = ::beman::execution::detail::spawn_t; -BEMAN_EXECUTION_EXPORT inline constexpr spawn_t spawn{}; +using spawn_t = ::beman::execution::detail::spawn_t; +inline constexpr spawn_t spawn{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/spawn_future.hpp b/include/beman/execution/detail/spawn_future.hpp index 86f36ce8..e3f8d646 100644 --- a/include/beman/execution/detail/spawn_future.hpp +++ b/include/beman/execution/detail/spawn_future.hpp @@ -262,8 +262,8 @@ struct impls_for : ::beman::execution::detail::default_impls { } // namespace beman::execution::detail namespace beman::execution { -BEMAN_EXECUTION_EXPORT using spawn_future_t = ::beman::execution::detail::spawn_future_t; -BEMAN_EXECUTION_EXPORT inline constexpr spawn_future_t spawn_future{}; +using spawn_future_t = ::beman::execution::detail::spawn_future_t; +inline constexpr spawn_future_t spawn_future{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/split.hpp b/include/beman/execution/detail/split.hpp index 150f1880..cbf4e67f 100644 --- a/include/beman/execution/detail/split.hpp +++ b/include/beman/execution/detail/split.hpp @@ -381,9 +381,9 @@ struct completion_signatures_for_impl< } // namespace beman::execution::detail namespace beman::execution { -BEMAN_EXECUTION_EXPORT using split_t = ::beman::execution::detail::split_t; +using split_t = ::beman::execution::detail::split_t; -BEMAN_EXECUTION_EXPORT inline constexpr ::beman::execution::split_t split{}; +inline constexpr ::beman::execution::split_t split{}; } // namespace beman::execution #endif // INCLUDED_BEMAN_EXECUTION_DETAIL_SPLIT diff --git a/include/beman/execution/detail/start.hpp b/include/beman/execution/detail/start.hpp index 9e62737a..06029f07 100644 --- a/include/beman/execution/detail/start.hpp +++ b/include/beman/execution/detail/start.hpp @@ -11,7 +11,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT struct start_t { +struct start_t { template auto operator()(State&&) const -> void = BEMAN_EXECUTION_DELETE("start(obj) requires an lvalue argument"); template @@ -44,7 +44,7 @@ BEMAN_EXECUTION_EXPORT struct start_t { // NOLINTEND(misc-no-recursion) }; -BEMAN_EXECUTION_EXPORT inline constexpr start_t start{}; +inline constexpr start_t start{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/starts_on.hpp b/include/beman/execution/detail/starts_on.hpp index 1a09d71a..381dfab9 100644 --- a/include/beman/execution/detail/starts_on.hpp +++ b/include/beman/execution/detail/starts_on.hpp @@ -54,8 +54,8 @@ struct starts_on_t { } // namespace beman::execution::detail namespace beman::execution { -BEMAN_EXECUTION_EXPORT using starts_on_t = ::beman::execution::detail::starts_on_t; -BEMAN_EXECUTION_EXPORT inline constexpr ::beman::execution::detail::starts_on_t starts_on{}; +using starts_on_t = ::beman::execution::detail::starts_on_t; +inline constexpr ::beman::execution::detail::starts_on_t starts_on{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/stop_callback_for_t.hpp b/include/beman/execution/detail/stop_callback_for_t.hpp index 9b658149..65233aca 100644 --- a/include/beman/execution/detail/stop_callback_for_t.hpp +++ b/include/beman/execution/detail/stop_callback_for_t.hpp @@ -10,7 +10,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT template +template using stop_callback_for_t = typename Token::template callback_type; } diff --git a/include/beman/execution/detail/stop_source.hpp b/include/beman/execution/detail/stop_source.hpp index d24752a6..cc7d59f2 100644 --- a/include/beman/execution/detail/stop_source.hpp +++ b/include/beman/execution/detail/stop_source.hpp @@ -16,11 +16,11 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT class stop_token; -BEMAN_EXECUTION_EXPORT class stop_source; -BEMAN_EXECUTION_EXPORT template +class stop_token; +class stop_source; +template class stop_callback; -BEMAN_EXECUTION_EXPORT template +template stop_callback(::beman::execution::stop_token, CallbackFun) -> stop_callback; } // namespace beman::execution diff --git a/include/beman/execution/detail/stop_token_of_t.hpp b/include/beman/execution/detail/stop_token_of_t.hpp index cb2ea4e5..263bade5 100644 --- a/include/beman/execution/detail/stop_token_of_t.hpp +++ b/include/beman/execution/detail/stop_token_of_t.hpp @@ -11,7 +11,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT template +template using stop_token_of_t = ::std::remove_cvref_t()))>; } diff --git a/include/beman/execution/detail/stoppable_source.hpp b/include/beman/execution/detail/stoppable_source.hpp index 3bad57a7..b75f0582 100644 --- a/include/beman/execution/detail/stoppable_source.hpp +++ b/include/beman/execution/detail/stoppable_source.hpp @@ -11,7 +11,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution::detail { -BEMAN_EXECUTION_EXPORT template //-dk:TODO detail export +template //-dk:TODO detail export concept stoppable_source = requires(Source& source, const Source& csource) { { csource.get_token() } -> ::beman::execution::stoppable_token; { csource.stop_possible() } noexcept -> ::std::same_as; diff --git a/include/beman/execution/detail/stoppable_token.hpp b/include/beman/execution/detail/stoppable_token.hpp index ac2f0add..ac737cd5 100644 --- a/include/beman/execution/detail/stoppable_token.hpp +++ b/include/beman/execution/detail/stoppable_token.hpp @@ -11,7 +11,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT template +template concept stoppable_token = requires(const Token& token) { typename ::beman::execution::detail::check_type_alias_exist; { token.stop_requested() } noexcept -> ::std::same_as; diff --git a/include/beman/execution/detail/sync_wait.hpp b/include/beman/execution/detail/sync_wait.hpp index ffceee6b..698bd95e 100644 --- a/include/beman/execution/detail/sync_wait.hpp +++ b/include/beman/execution/detail/sync_wait.hpp @@ -26,22 +26,21 @@ // ---------------------------------------------------------------------------- namespace beman::execution::detail { -BEMAN_EXECUTION_EXPORT struct sync_wait_env { // dk:TODO detail export +struct sync_wait_env { // dk:TODO detail export ::beman::execution::run_loop* loop{}; auto query(::beman::execution::get_scheduler_t) const noexcept { return this->loop->get_scheduler(); } auto query(::beman::execution::get_delegation_scheduler_t) const noexcept { return this->loop->get_scheduler(); } }; -BEMAN_EXECUTION_EXPORT template < - ::beman::execution::sender_in<::beman::execution::detail::sync_wait_env> Sender> // dk:TODO detail export +template <::beman::execution::sender_in<::beman::execution::detail::sync_wait_env> Sender> // dk:TODO detail export using sync_wait_result_type = ::std::optional<::beman::execution::value_types_of_t>; -BEMAN_EXECUTION_EXPORT template // dk:TODO detail export +template // dk:TODO detail export struct sync_wait_state { ::beman::execution::run_loop loop{}; ::std::exception_ptr error{}; @@ -49,7 +48,7 @@ struct sync_wait_state { ::beman::execution::detail::sync_wait_result_type result{}; }; -BEMAN_EXECUTION_EXPORT template // dk:TODO detail export +template // dk:TODO detail export struct sync_wait_receiver { using receiver_concept = ::beman::execution::receiver_t; @@ -109,7 +108,7 @@ struct sync_wait_t { } // namespace beman::execution::detail namespace beman::execution { -BEMAN_EXECUTION_EXPORT using sync_wait_t = ::beman::execution::detail::sync_wait_t; +using sync_wait_t = ::beman::execution::detail::sync_wait_t; /*! * \brief sync_wait(_sender_) starts _sender_ and waits for its completion. * \headerfile beman/execution/execution.hpp @@ -157,7 +156,7 @@ BEMAN_EXECUTION_EXPORT using sync_wait_t = ::beman::execution::detail::sync_wait * } * */ -BEMAN_EXECUTION_EXPORT inline constexpr ::beman::execution::sync_wait_t sync_wait{}; +inline constexpr ::beman::execution::sync_wait_t sync_wait{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/tag_of_t.hpp b/include/beman/execution/detail/tag_of_t.hpp index 7a83c2fb..166ee288 100644 --- a/include/beman/execution/detail/tag_of_t.hpp +++ b/include/beman/execution/detail/tag_of_t.hpp @@ -11,7 +11,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT template +template using tag_of_t = typename decltype(::beman::execution::detail::get_sender_meta(::std::declval()))::tag_type; } diff --git a/include/beman/execution/detail/then.hpp b/include/beman/execution/detail/then.hpp index c393b0fc..c8b9db80 100644 --- a/include/beman/execution/detail/then.hpp +++ b/include/beman/execution/detail/then.hpp @@ -58,31 +58,34 @@ struct then_t : ::beman::execution::sender_adaptor_closure> { template struct impls_for> : ::beman::execution::detail::default_impls { // NOLINTBEGIN(bugprone-exception-escape) - static constexpr auto complete = - [](auto, auto& fun, auto& receiver, Tag, Args&&... args) noexcept -> void { - if constexpr (::std::same_as) { - try { - auto invoke = [&] { return ::std::invoke(::std::move(fun), ::std::forward(args)...); }; - if constexpr (::std::same_as) { - invoke(); - ::beman::execution::set_value(::std::move(receiver)); - } else { - ::beman::execution::set_value(::std::move(receiver), invoke()); - } - } catch (...) { - if constexpr (not noexcept(::std::invoke(::std::move(fun), ::std::forward(args)...) + struct complete_impl { + template + auto operator()(auto, auto& fun, auto& receiver, Tag, Args&&... args) const noexcept -> void { + if constexpr (::std::same_as) { + try { + auto invoke = [&] { return ::std::invoke(::std::move(fun), ::std::forward(args)...); }; + if constexpr (::std::same_as) { + invoke(); + ::beman::execution::set_value(::std::move(receiver)); + } else { + ::beman::execution::set_value(::std::move(receiver), invoke()); + } + } catch (...) { + if constexpr (not noexcept(::std::invoke(::std::move(fun), ::std::forward(args)...) - )) { - static_assert( - noexcept(::beman::execution::set_error(::std::move(receiver), ::std::current_exception()))); - ::beman::execution::set_error(::std::move(receiver), ::std::current_exception()); + )) { + static_assert(noexcept( + ::beman::execution::set_error(::std::move(receiver), ::std::current_exception()))); + ::beman::execution::set_error(::std::move(receiver), ::std::current_exception()); + } } + } else { + static_assert(noexcept(Tag()(::std::move(receiver), ::std::forward(args)...))); + Tag()(::std::move(receiver), ::std::forward(args)...); } - } else { - static_assert(noexcept(Tag()(::std::move(receiver), ::std::forward(args)...))); - Tag()(::std::move(receiver), ::std::forward(args)...); } }; + static constexpr auto complete{complete_impl{}}; // NOLINTEND(bugprone-exception-escape) }; @@ -150,17 +153,17 @@ namespace beman::execution { * \brief then_t is the type of then. * \headerfile beman/execution/execution.hpp */ -BEMAN_EXECUTION_EXPORT using then_t = ::beman::execution::detail::then_t<::beman::execution::set_value_t>; +using then_t = ::beman::execution::detail::then_t<::beman::execution::set_value_t>; /*! * \brief upon_error_t is the type of upon_error. * \headerfile beman/execution/execution.hpp */ -BEMAN_EXECUTION_EXPORT using upon_error_t = ::beman::execution::detail::then_t<::beman::execution::set_error_t>; +using upon_error_t = ::beman::execution::detail::then_t<::beman::execution::set_error_t>; /*! * \brief upon_stopped_t is the type of upon_stopped. * \headerfile beman/execution/execution.hpp */ -BEMAN_EXECUTION_EXPORT using upon_stopped_t = ::beman::execution::detail::then_t<::beman::execution::set_stopped_t>; +using upon_stopped_t = ::beman::execution::detail::then_t<::beman::execution::set_stopped_t>; /*! * \brief then(_sender_, _fun_) yields a sender transforming a set_value_t(_A_...) completion @@ -212,7 +215,7 @@ BEMAN_EXECUTION_EXPORT using upon_stopped_t = ::beman::execution::detail::then_t * } * */ -BEMAN_EXECUTION_EXPORT inline constexpr ::beman::execution::then_t then{}; +inline constexpr ::beman::execution::then_t then{}; /*! * \brief upon_error(_sender_, _fun_) yields a sender transforming a set_error_t(_E_) @@ -266,7 +269,7 @@ BEMAN_EXECUTION_EXPORT inline constexpr ::beman::execution::then_t then{}; * } * */ -BEMAN_EXECUTION_EXPORT inline constexpr ::beman::execution::upon_error_t upon_error{}; +inline constexpr ::beman::execution::upon_error_t upon_error{}; /*! * \brief upon_stopped(_sender_, _fun_) yields a sender transforming a set_stopped_t() @@ -317,7 +320,7 @@ BEMAN_EXECUTION_EXPORT inline constexpr ::beman::execution::upon_error_t upon_er * } * */ -BEMAN_EXECUTION_EXPORT inline constexpr ::beman::execution::upon_stopped_t upon_stopped{}; +inline constexpr ::beman::execution::upon_stopped_t upon_stopped{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/transform_sender.hpp b/include/beman/execution/detail/transform_sender.hpp index 10ec17d4..c7ca9bb3 100644 --- a/include/beman/execution/detail/transform_sender.hpp +++ b/include/beman/execution/detail/transform_sender.hpp @@ -66,7 +66,7 @@ constexpr auto transform_sender(Domain dom, Sender&& sender, const Env&... env) } // namespace beman::execution::detail namespace beman::execution { -BEMAN_EXECUTION_EXPORT template +template requires(sizeof...(Env) < 2) && requires(Domain dom, Sender&& sender, const Env&... env) { dom.transform_sender(::std::forward(sender), env...); @@ -79,7 +79,7 @@ constexpr auto transform_sender(Domain, Sender&& sender, const Env&...) noexcept return ::std::forward(sender); } -BEMAN_EXECUTION_EXPORT template +template requires(sizeof...(Env) < 2) && requires(Domain dom, Sender&& sender, const Env&... env) { dom.transform_sender(::std::forward(sender), env...); @@ -93,7 +93,7 @@ constexpr auto transform_sender(Domain dom, Sender&& sender, const Env&... env) dom, dom.transform_sender(::std::forward(sender), env...), env...); } -BEMAN_EXECUTION_EXPORT template +template requires(sizeof...(Env) < 2) && (not requires(Domain dom, Sender&& sender, const Env&... env) { dom.transform_sender(::std::forward(sender), env...); }) && @@ -106,7 +106,7 @@ constexpr auto return ::std::forward(sender); } -BEMAN_EXECUTION_EXPORT template +template requires(sizeof...(Env) < 2) && (not requires(Domain dom, Sender&& sender, const Env&... env) { dom.transform_sender(::std::forward(sender), env...); }) && diff --git a/include/beman/execution/detail/unstoppable_token.hpp b/include/beman/execution/detail/unstoppable_token.hpp index b1d4bc97..75c9e561 100644 --- a/include/beman/execution/detail/unstoppable_token.hpp +++ b/include/beman/execution/detail/unstoppable_token.hpp @@ -11,7 +11,7 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT template +template concept unstoppable_token = ::beman::execution::stoppable_token && requires() { requires ::std::bool_constant::value; }; } // namespace beman::execution diff --git a/include/beman/execution/detail/valid_completion_for.hpp b/include/beman/execution/detail/valid_completion_for.hpp index 9b69b057..24048377 100644 --- a/include/beman/execution/detail/valid_completion_for.hpp +++ b/include/beman/execution/detail/valid_completion_for.hpp @@ -24,7 +24,7 @@ struct valid_completion_for_aux { {} }; -BEMAN_EXECUTION_EXPORT template // dk:TODO detail export +template // dk:TODO detail export concept valid_completion_for = requires(Signature* signature) { #if 1 valid_completion_for_aux::test(signature); diff --git a/include/beman/execution/detail/value_types_of_t.hpp b/include/beman/execution/detail/value_types_of_t.hpp index 1c279184..eb5508d7 100644 --- a/include/beman/execution/detail/value_types_of_t.hpp +++ b/include/beman/execution/detail/value_types_of_t.hpp @@ -15,10 +15,10 @@ // ---------------------------------------------------------------------------- namespace beman::execution { -BEMAN_EXECUTION_EXPORT template , - template class Tuple = ::beman::execution::detail::decayed_tuple, - template class Variant = ::beman::execution::detail::variant_or_empty> +template , + template class Tuple = ::beman::execution::detail::decayed_tuple, + template class Variant = ::beman::execution::detail::variant_or_empty> requires ::beman::execution::sender_in using value_types_of_t = ::beman::execution::detail::gather_signatures<::beman::execution::set_value_t, diff --git a/include/beman/execution/detail/when_all.hpp b/include/beman/execution/detail/when_all.hpp index 031bd7d0..fe74a6d2 100644 --- a/include/beman/execution/detail/when_all.hpp +++ b/include/beman/execution/detail/when_all.hpp @@ -78,20 +78,26 @@ struct when_all_value_types<::beman::execution::detail::type_list> { template <> struct impls_for<::beman::execution::detail::when_all_t> : ::beman::execution::detail::default_impls { - static constexpr auto get_attrs{[](auto&&, auto&&... sender) { - using common_t = - typename ::std::common_type_t; - if constexpr (::std::same_as) - return ::beman::execution::env<>{}; - else - return ::beman::execution::detail::make_env(::beman::execution::get_domain, common_t{}); - }}; - static constexpr auto get_env{ - [](auto&&, State& state, const Receiver& receiver) noexcept { + struct get_attrs_impl { + auto operator()(auto&&, auto&&... sender) const { + using common_t = + typename ::std::common_type_t; + if constexpr (::std::same_as) + return ::beman::execution::env<>{}; + else + return ::beman::execution::detail::make_env(::beman::execution::get_domain, common_t{}); + } + }; + static constexpr auto get_attrs{get_attrs_impl{}}; + struct get_env_impl { + template + auto operator()(auto&&, State& state, const Receiver& receiver) const noexcept { return ::beman::execution::detail::join_env( ::beman::execution::detail::make_env(::beman::execution::get_stop_token, state.stop_src.get_token()), ::beman::execution::get_env(receiver)); - }}; + } + }; + static constexpr auto get_env{get_env_impl{}}; enum class disposition : unsigned char { started, error, stopped }; @@ -183,25 +189,32 @@ struct impls_for<::beman::execution::detail::when_all_t> : ::beman::execution::d return state_type{}; } }; - static constexpr auto get_state{[](Sender&& sender, Receiver&) noexcept( - noexcept(std::forward(sender).apply(make_state{}))) { - return std::forward(sender).apply(make_state{}); - }}; - static constexpr auto start{[]( - State& state, Receiver& receiver, Ops&... ops) noexcept -> void { - state.receiver = &receiver; - state.on_stop.emplace(::beman::execution::get_stop_token(::beman::execution::get_env(receiver)), - ::beman::execution::detail::on_stop_request{state}); - if (state.stop_src.stop_requested()) { - state.on_stop.reset(); - ::beman::execution::set_stopped(std::move(receiver)); - } else { - (::beman::execution::start(ops), ...); + struct get_state_impl { + template + auto operator()(Sender&& sender, Receiver&) const + noexcept(noexcept(std::forward(sender).apply(make_state{}))) { + return std::forward(sender).apply(make_state{}); } - }}; - static constexpr auto complete{ - []( - Index, State& state, Receiver& receiver, Set, Args&&... args) noexcept -> void { + }; + static constexpr auto get_state{get_state_impl{}}; + struct start_impl { + template + auto operator()(State& state, Receiver& receiver, Ops&... ops) const noexcept -> void { + state.receiver = &receiver; + state.on_stop.emplace(::beman::execution::get_stop_token(::beman::execution::get_env(receiver)), + ::beman::execution::detail::on_stop_request{state}); + if (state.stop_src.stop_requested()) { + state.on_stop.reset(); + ::beman::execution::set_stopped(std::move(receiver)); + } else { + (::beman::execution::start(ops), ...); + } + } + }; + static constexpr auto start{start_impl{}}; + struct complete_impl { + template + auto operator()(Index, State& state, Receiver& receiver, Set, Args&&... args) const noexcept -> void { if constexpr (::std::same_as) { if (disposition::error != state.disp.exchange(disposition::error)) { state.stop_src.request_stop(); @@ -231,7 +244,9 @@ struct impls_for<::beman::execution::detail::when_all_t> : ::beman::execution::d } } state.arrive(receiver); - }}; + } + }; + static constexpr auto complete{complete_impl{}}; }; template @@ -261,8 +276,8 @@ struct completion_signatures_for_impl< } // namespace beman::execution::detail namespace beman::execution { -BEMAN_EXECUTION_EXPORT using when_all_t = ::beman::execution::detail::when_all_t; -BEMAN_EXECUTION_EXPORT inline constexpr ::beman::execution::when_all_t when_all{}; +using when_all_t = ::beman::execution::detail::when_all_t; +inline constexpr ::beman::execution::when_all_t when_all{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/when_all_with_variant.hpp b/include/beman/execution/detail/when_all_with_variant.hpp index 5a37adc9..5d1882f8 100644 --- a/include/beman/execution/detail/when_all_with_variant.hpp +++ b/include/beman/execution/detail/when_all_with_variant.hpp @@ -41,8 +41,8 @@ struct when_all_with_variant_t { } // namespace beman::execution::detail namespace beman::execution { -BEMAN_EXECUTION_EXPORT using when_all_with_variant_t = ::beman::execution::detail::when_all_with_variant_t; -BEMAN_EXECUTION_EXPORT inline constexpr ::beman::execution::when_all_with_variant_t when_all_with_variant{}; +using when_all_with_variant_t = ::beman::execution::detail::when_all_with_variant_t; +inline constexpr ::beman::execution::when_all_with_variant_t when_all_with_variant{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/include/beman/execution/detail/with_awaitable_senders.hpp b/include/beman/execution/detail/with_awaitable_senders.hpp index a744a3dc..c9b2610a 100644 --- a/include/beman/execution/detail/with_awaitable_senders.hpp +++ b/include/beman/execution/detail/with_awaitable_senders.hpp @@ -12,7 +12,7 @@ #include namespace beman::execution { -BEMAN_EXECUTION_EXPORT template <::beman::execution::detail::class_type Promise> +template <::beman::execution::detail::class_type Promise> struct with_awaitable_senders { template requires(!::std::same_as) diff --git a/include/beman/execution/detail/write_env.hpp b/include/beman/execution/detail/write_env.hpp index 1cfc3e60..c55dae1d 100644 --- a/include/beman/execution/detail/write_env.hpp +++ b/include/beman/execution/detail/write_env.hpp @@ -44,17 +44,20 @@ struct completion_signatures_for_impl< template <> struct impls_for : ::beman::execution::detail::default_impls { - static constexpr auto get_env = [](auto, const auto& state, const auto& receiver) noexcept { - return ::beman::execution::detail::join_env(state, ::beman::execution::get_env(receiver)); + struct get_env_impl { + auto operator()(auto, const auto& state, const auto& receiver) const noexcept { + return ::beman::execution::detail::join_env(state, ::beman::execution::get_env(receiver)); + } }; + static constexpr auto get_env = get_env_impl{}; }; inline constexpr write_env_t write_env{}; } // namespace beman::execution::detail namespace beman::execution { -BEMAN_EXECUTION_EXPORT using write_env_t = ::beman::execution::detail::write_env_t; -BEMAN_EXECUTION_EXPORT inline constexpr write_env_t write_env{}; +using write_env_t = ::beman::execution::detail::write_env_t; +inline constexpr write_env_t write_env{}; } // namespace beman::execution // ---------------------------------------------------------------------------- diff --git a/src/beman/execution/execution.cppm b/src/beman/execution/execution.cppm index e54eb38a..5ff6ed6a 100644 --- a/src/beman/execution/execution.cppm +++ b/src/beman/execution/execution.cppm @@ -1,6472 +1,258 @@ module; +// src/beman/execution/execution-using.cppm // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// *****************************************************; -// *** WARNING: this file is generated: do not edit! ***; -// *****************************************************; -// generated by ./bin/mk-module.py src/beman/execution/execution.cppm -#include -#include - -#ifdef BEMAN_HAS_IMPORT_STD -import std; -#else -#line 239 "./bin/mk-module.py" -#include -#line 239 "./bin/mk-module.py" -#include -#line 239 "./bin/mk-module.py" -#include -#line 239 "./bin/mk-module.py" -#include -#line 239 "./bin/mk-module.py" -#include -#line 239 "./bin/mk-module.py" -#include -#line 239 "./bin/mk-module.py" -#include -#line 239 "./bin/mk-module.py" -#include -#line 239 "./bin/mk-module.py" -#include -#line 239 "./bin/mk-module.py" -#include -#line 239 "./bin/mk-module.py" -#include -#line 239 "./bin/mk-module.py" -#include -#line 239 "./bin/mk-module.py" -#include -#line 239 "./bin/mk-module.py" -#include -#line 239 "./bin/mk-module.py" -#include -#line 239 "./bin/mk-module.py" -#include -#line 239 "./bin/mk-module.py" -#include -#line 239 "./bin/mk-module.py" -#include -#line 239 "./bin/mk-module.py" -#include -#endif +#include +#include export module beman.execution; -#line 5 "include/beman/execution/execution.hpp" - -#line 9 "include/beman/execution/detail/common.hpp" -#ifndef BEMAN_EXECUTION_EXPORT -#define BEMAN_EXECUTION_EXPORT -#endif - -#if defined(disabled__cpp_deleted_function) -#define BEMAN_EXECUTION_DELETE(msg) delete (msg) -#else -#define BEMAN_EXECUTION_DELETE(msg) delete -#endif - -#line 43 "include/beman/execution/detail/common.hpp" -namespace beman { - -#line 54 "include/beman/execution/detail/common.hpp" -namespace execution { - -#line 61 "include/beman/execution/detail/common.hpp" -namespace detail {} -} // namespace execution -} // namespace beman - -#line 6 "include/beman/execution/detail/suppress_push.hpp" -#if defined(__GNUC__) -#define BEMAN_EXECUTION_DIAGNOSTIC_PUSHED -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wmissing-braces" -#pragma GCC diagnostic ignored "-Wmissing-field-initializers" -#endif - -#if defined(__clang__) -#define BEMAN_EXECUTION_DIAGNOSTIC_PUSHED -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunknown-warning-option" -#pragma clang diagnostic ignored "-Wmissing-braces" -#pragma clang diagnostic ignored "-Wc++26-extensions" -#endif -#line 3 "include/beman/execution/detail/suppress_pop.hpp" - -#line 6 "include/beman/execution/detail/suppress_pop.hpp" -#ifdef BEMAN_EXECUTION_DIAGNOSTIC_PUSHED -#if defined(__GNUC__) -#pragma GCC diagnostic pop -#endif -#if defined(__clang__) -#pragma clang diagnostic pop -#endif -#undef BEMAN_EXECUTION_DIAGNOSTIC_PUSHED -#endif -#line 3 "include/beman/execution/detail/queryable.hpp" - -#line 12 "include/beman/execution/detail/queryable.hpp" -namespace beman::execution::detail { -template -concept queryable = ::std::destructible; -} -#line 14 "include/beman/execution/detail/forwarding_query.hpp" -namespace beman::execution::detail { - -#line 20 "include/beman/execution/detail/forwarding_query.hpp" -struct forwarding_query_t { - template - requires requires(Object&& object, const forwarding_query_t& query) { - { ::std::forward(object).query(query) } noexcept -> ::std::same_as; - } - constexpr auto operator()(Object&& object) const noexcept -> bool { - return ::std::forward(object).query(*this); - } - template - constexpr auto operator()(Object&&) const noexcept -> bool { - return ::std::derived_from<::std::remove_cvref_t, ::beman::execution::detail::forwarding_query_t>; - } -}; -} // namespace beman::execution::detail - -namespace beman::execution { - -#line 40 "include/beman/execution/detail/forwarding_query.hpp" -export /* --------- */ using forwarding_query_t = beman::execution::detail::forwarding_query_t; - -#line 53 "include/beman/execution/detail/forwarding_query.hpp" -export /* --------- */ inline constexpr forwarding_query_t forwarding_query{}; -} // namespace beman::execution - -#line 13 "include/beman/execution/detail/movable_value.hpp" -namespace beman::execution::detail { -template -concept movable_value = - ::std::move_constructible<::std::decay_t> && ::std::constructible_from<::std::decay_t, T> && - (!::std::is_array_v<::std::remove_reference_t>); -} -#line 12 "include/beman/execution/detail/matching_sig.hpp" -namespace beman::execution::detail { -template -struct matching_sig_transform { - using type = Fun; -}; -template -struct matching_sig_transform { - using type = Return(Args&&...); -}; - -template -inline constexpr bool matching_sig = - ::std::same_as::type, - typename ::beman::execution::detail::matching_sig_transform::type>; -} // namespace beman::execution::detail - -#line 17 "include/beman/execution/detail/as_except_ptr.hpp" -namespace beman::execution::detail { - -#line 23 "include/beman/execution/detail/as_except_ptr.hpp" -template -decltype(auto) as_except_ptr(Error&& error) { - if constexpr (::std::same_as<::std::exception_ptr, ::std::decay_t>) { - return ::std::forward(error); - } else if constexpr (::std::same_as<::std::error_code, ::std::decay_t>) { - return ::std::make_exception_ptr(::std::system_error(error)); - } else { - return ::std::make_exception_ptr(::std::forward(error)); - } -} -} // namespace beman::execution::detail - -#line 14 "include/beman/execution/detail/set_value.hpp" -namespace beman::execution { - -#line 19 "include/beman/execution/detail/set_value.hpp" -export /* --------- */ struct set_value_t { - template - auto operator()(Receiver&, Args&&...) const - -> void = BEMAN_EXECUTION_DELETE("set_value requires the receiver to be passed as non-const rvalue"); - template - auto operator()(const Receiver&&, Args&&...) const - -> void = BEMAN_EXECUTION_DELETE("set_value requires the receiver to be passed as non-const rvalue"); - template - auto operator()(Receiver&&, Args&&...) const -> void - requires(not requires(Receiver&& receiver, Args&&... args) { - ::std::forward(receiver).set_value(::std::forward(args)...); - }) - = BEMAN_EXECUTION_DELETE("set_value requires a suitable member overload on the receiver"); - template - requires(not noexcept(::std::declval().set_value(::std::declval()...))) - auto operator()(Receiver&&, Args&&...) const - -> void = BEMAN_EXECUTION_DELETE("the call to receiver.set_value(args...) has to be noexcept"); - - template - auto operator()(Receiver&& receiver, Args&&... args) const noexcept -> void { - ::std::forward(receiver).set_value(::std::forward(args)...); - } -}; - -#line 47 "include/beman/execution/detail/set_value.hpp" -export /* --------- */ inline constexpr set_value_t set_value{}; -} // namespace beman::execution - -#line 14 "include/beman/execution/detail/set_error.hpp" -namespace beman::execution { - -#line 19 "include/beman/execution/detail/set_error.hpp" -export /* --------- */ struct set_error_t { - template - auto operator()(Receiver&, Error&&) const - -> void = BEMAN_EXECUTION_DELETE("set_error requires the receiver to be passed as non-const rvalue"); - template - auto operator()(const Receiver&&, Error&&) const - -> void = BEMAN_EXECUTION_DELETE("set_error requires the receiver to be passed as non-const rvalue"); - template - auto operator()(Receiver&&, Error&&) const -> void - requires(not requires(Receiver&& receiver, Error&& error) { - ::std::forward(receiver).set_error(::std::forward(error)); - }) - = BEMAN_EXECUTION_DELETE("set_error requires a suitable member overload on the receiver"); - template - requires(not noexcept(::std::declval().set_error(::std::declval()))) - auto operator()(Receiver&&, Error&&) const - -> void = BEMAN_EXECUTION_DELETE("the call to receiver.set_error(error) has to be noexcept"); - - // NOLINTBEGIN(misc-no-recursion) - template - auto operator()(Receiver&& receiver, Error&& error) const noexcept -> void { - ::std::forward(receiver).set_error(::std::forward(error)); - } - // NOLINTEND(misc-no-recursion) -}; - -#line 49 "include/beman/execution/detail/set_error.hpp" -export /* --------- */ inline constexpr set_error_t set_error{}; -} // namespace beman::execution - -#line 14 "include/beman/execution/detail/set_stopped.hpp" -namespace beman::execution { - -#line 19 "include/beman/execution/detail/set_stopped.hpp" -export /* --------- */ struct set_stopped_t { - template - auto operator()(Receiver&) const - -> void = BEMAN_EXECUTION_DELETE("set_stopped requires the receiver to be passed as non-const rvalue"); - template - auto operator()(const Receiver&&) const - -> void = BEMAN_EXECUTION_DELETE("set_stopped requires the receiver to be passed as non-const rvalue"); - template - auto operator()(Receiver&&) const -> void - requires(not requires(Receiver&& receiver) { ::std::forward(receiver).set_stopped(); }) - = BEMAN_EXECUTION_DELETE("set_stopped requires a suitable member overload on the receiver"); - template - requires(not noexcept(::std::declval().set_stopped())) - auto operator()(Receiver&&) const - -> void = BEMAN_EXECUTION_DELETE("the call to receiver.set_stopped() has to be noexcept"); - - template - auto operator()(Receiver&& receiver) const noexcept -> void { - ::std::forward(receiver).set_stopped(); - } -}; - -#line 45 "include/beman/execution/detail/set_stopped.hpp" -export /* --------- */ inline constexpr set_stopped_t set_stopped{}; -} // namespace beman::execution - -#line 13 "include/beman/execution/detail/start.hpp" namespace beman::execution { -export /* --------- */ struct start_t { - template - auto operator()(State&&) const -> void = BEMAN_EXECUTION_DELETE("start(obj) requires an lvalue argument"); - template - requires(not requires(State& state) { state.start(); }) - auto operator()(State&) const -> void = BEMAN_EXECUTION_DELETE("state needs to have a start() member"); - template - requires(not requires(const State& state) { state.start(); }) - auto operator()(const State&) const -> void = BEMAN_EXECUTION_DELETE("state needs to have a start() member"); - - template - requires(not requires(State& state) { - { state.start() } noexcept; - }) - auto operator()(State&) const -> void = BEMAN_EXECUTION_DELETE("state start() member has to be noexcept"); - template - requires(not requires(const State& state) { - { state.start() } noexcept; - }) - auto operator()(const State&) const -> void = BEMAN_EXECUTION_DELETE("state start() member has to be noexcept"); +export using beman::execution::detail::pipeable::operator|; - template - auto operator()(const State& state) const noexcept -> void { - state.start(); - } - // NOLINTBEGIN(misc-no-recursion) - template - auto operator()(State& state) const noexcept -> void { - state.start(); - } - // NOLINTEND(misc-no-recursion) -}; +// [stoptoken.concepts], stop token concepts +export using ::beman::execution::stoppable_token; +export using ::beman::execution::unstoppable_token; -export /* --------- */ inline constexpr start_t start{}; -} // namespace beman::execution - -#line 11 "include/beman/execution/detail/non_assignable.hpp" -namespace beman::execution::detail { -struct non_assignable; -} -#line 17 "include/beman/execution/detail/non_assignable.hpp" -struct beman::execution::detail::non_assignable { - non_assignable() = default; - non_assignable(non_assignable&&) = default; - non_assignable(const non_assignable&) = default; - auto operator=(non_assignable&&) -> non_assignable& = delete; - auto operator=(const non_assignable&) -> non_assignable& = delete; -}; - -#line 13 "include/beman/execution/detail/simple_allocator.hpp" -namespace beman::execution::detail { -export /* --------- */ template -concept simple_allocator = - requires(::std::remove_cvref_t alloc, ::std::size_t n) { - { *alloc.allocate(n) } -> ::std::same_as::value_type&>; - alloc.deallocate(alloc.allocate(n), n); - } && ::std::copy_constructible<::std::remove_cvref_t> && - ::std::equality_comparable<::std::remove_cvref_t>; -} // namespace beman::execution::detail - -#line 11 "include/beman/execution/detail/never_stop_token.hpp" -namespace beman::execution { -export /* --------- */ class never_stop_token; -} -#line 17 "include/beman/execution/detail/never_stop_token.hpp" -class beman::execution::never_stop_token { - struct private_callback_type { - explicit private_callback_type(never_stop_token, auto&&) noexcept {} - }; - - public: - template - using callback_type = private_callback_type; +// [stoptoken], class stop_token +export using ::beman::execution::stop_token; - static constexpr auto stop_requested() noexcept -> bool { return {}; } - static constexpr auto stop_possible() noexcept -> bool { return {}; } - auto operator==(const never_stop_token&) const -> bool = default; -}; +// [stopsource], class stop_source +export using ::beman::execution::stop_source; -#line 12 "include/beman/execution/detail/decayed_same_as.hpp" -namespace beman::execution::detail { +export using ::beman::execution::nostopstate_t; +export using ::beman::execution::nostopstate; -#line 19 "include/beman/execution/detail/decayed_same_as.hpp" -template -concept decayed_same_as = ::std::same_as<::std::remove_cvref_t, ::std::remove_cvref_t>; -} // namespace beman::execution::detail +// [stopcallback], class template stop_callback +export using ::beman::execution::stop_callback; -#line 12 "include/beman/execution/detail/callable.hpp" -namespace beman::execution::detail { +// [stoptoken.never], class never_stop_token +export using ::beman::execution::never_stop_token; -#line 19 "include/beman/execution/detail/callable.hpp" -template -concept callable = requires(Fun&& fun, Args&&... args) { ::std::forward(fun)(::std::forward(args)...); }; -} // namespace beman::execution::detail +// [stoptoken.inplace], class inplace_stop_token +export using ::beman::execution::inplace_stop_token; -#line 15 "include/beman/execution/detail/forward_like.hpp" -namespace beman::execution::detail { -template -struct forward_like_helper; +// [stopsource.inplace], class inplace_stop_source +export using ::beman::execution::inplace_stop_source; -template -struct forward_like_helper { - template - static auto forward(U&& u) -> ::std::remove_reference_t&& { - return ::std::move(u); // NOLINT(bugprone-move-forwarding-reference) - } -}; -template -struct forward_like_helper { - template - static auto forward(U&& u) -> ::std::remove_cvref_t&& { - return ::std::move(u); // NOLINT(bugprone-move-forwarding-reference) - } -}; -template -struct forward_like_helper { - template - static auto forward(U&& u) -> ::std::remove_cvref_t& { - return ::std::forward(u); - } -}; -template -struct forward_like_helper { - template - static auto forward(U&& u) -> const ::std::remove_cvref_t&& { - return ::std::move(u); // NOLINT(bugprone-move-forwarding-reference) - } -}; -template -struct forward_like_helper { - template - static auto forward(U&& u) -> const ::std::remove_cvref_t& { - return ::std::forward(u); - } -}; +// [stopcallback.inplace], class template inplace_stop_callback +export using ::beman::execution::inplace_stop_callback; +export using ::beman::execution::stop_callback_for_t; -#line 57 "include/beman/execution/detail/forward_like.hpp" -template -auto own_forward_like(U&& u) noexcept -> decltype(auto) { - return ::beman::execution::detail::forward_like_helper::forward(::std::forward(u)); -} -#line 67 "include/beman/execution/detail/forward_like.hpp" -template -auto forward_like(U&& u) noexcept -> decltype(auto) { -#if 202207 <= disabled__cpp_lib_forward_like - return ::std::forward_like(::std::forward(u)); -#else - return ::beman::execution::detail::forward_like_helper::forward(::std::forward(u)); +#if 0 + //-dk:TODO enable the execution policies + export using ::std::is_execution_policy; + export using ::std::is_execution_policy_v; + + export using ::std::execution::sequenced_policy; + export using ::std::execution::parallel_policy; + export using ::std::execution::parallel_unsequenced_policy; + export using ::std::execution::unsequenced_policy; + + export using ::std::execution::seq; + export using ::std::execution::par; + export using ::std::execution::par_unseq; + export using ::std::execution::unseq; #endif -} -#line 76 "include/beman/execution/detail/forward_like.hpp" -} // namespace beman::execution::detail - -#line 13 "include/beman/execution/detail/join_env.hpp" -namespace beman::execution::detail { -template -class join_env { - private: - Env1 env1; - Env2 env2; - - public: - template - join_env(E1&& e1, E2&& e2) : env1(::std::forward(e1)), env2(::std::forward(e2)) {} - - template - requires requires(Env1&, const Query& query, Args&&... args) { - env1.query(query, ::std::forward(args)...); - } - auto query(const Query& query, Args&&... args) noexcept -> decltype(auto) { - return this->env1.query(query, ::std::forward(args)...); - } - template - requires( - not requires(Env1&, const Query& query, Args&&... args) { - env1.query(query, ::std::forward(args)...); - } && - requires(Env2& e2, const Query& query, Args&&... args) { e2.query(query, ::std::forward(args)...); }) - auto query(const Query& query, Args&&... args) noexcept -> decltype(auto) { - return this->env2.query(query, ::std::forward(args)...); - } - template - requires requires(const Env1& e1, const Query& query, Args&&... args) { - { e1.query(query, ::std::forward(args)...) } noexcept; - } - auto query(const Query& query, Args&&... args) const noexcept -> decltype(auto) { - return this->env1.query(query, ::std::forward(args)...); - } - template - requires( - not requires(const Env1& e1, const Query& query, Args&&... args) { - { e1.query(query, ::std::forward(args)...) } noexcept; - } && - requires(const Env2& e2, const Query& query, Args&&... args) { - { e2.query(query, ::std::forward(args)...) } noexcept; - }) - auto query(const Query& query, Args&&... args) const noexcept -> decltype(auto) { - return this->env2.query(query, ::std::forward(args)...); - } -}; - -template -join_env(Env1&&, Env2&&) -> join_env<::std::remove_cvref_t, ::std::remove_cvref_t>; -} // namespace beman::execution::detail - -#line 15 "include/beman/execution/detail/product_type.hpp" -namespace beman::execution::detail { - -template <::std::size_t I, typename T> -struct product_type_element { - T value; - auto operator==(const product_type_element&) const -> bool = default; -}; - -template -struct product_type_base; - -template <::std::size_t... I, typename... T> -struct product_type_base<::std::index_sequence, T...> - : ::beman::execution::detail::product_type_element... { - static constexpr ::std::size_t size() { return sizeof...(T); } - static constexpr bool is_product_type{true}; - - template <::std::size_t J, typename S> - static auto element_get(::beman::execution::detail::product_type_element& self) noexcept -> S& { - return self.value; - } - template <::std::size_t J, typename S> - static auto element_get(::beman::execution::detail::product_type_element&& self) noexcept -> S&& { - return ::std::move(self.value); - } - template <::std::size_t J, typename S> - static auto element_get(const ::beman::execution::detail::product_type_element& self) noexcept -> const S& { - return self.value; - } -#line 45 "include/beman/execution/detail/product_type.hpp" - template <::std::size_t J> - auto get() & -> decltype(auto) { - return this->element_get(*this); - } - template <::std::size_t J> - auto get() && -> decltype(auto) { - return this->element_get(::std::move(*this)); - } - template <::std::size_t J> - auto get() const& -> decltype(auto) { - return this->element_get(*this); - } -#line 58 "include/beman/execution/detail/product_type.hpp" - template <::std::size_t J, typename Allocator, typename Self> - static auto make_element(Allocator&& alloc, Self&& self) -> decltype(auto) { - using type = ::std::remove_cvref_t(std::forward(self)))>; - if constexpr (::std::uses_allocator_v) - return ::std::make_obj_using_allocator(alloc, - product_type_base::element_get(std::forward(self))); - else - return product_type_base::element_get(std::forward(self)); - } -#line 68 "include/beman/execution/detail/product_type.hpp" - auto operator==(const product_type_base&) const -> bool = default; -}; -template -concept is_product_type_c = requires(const T& t) { T::is_product_type; }; +// [exec.queries], queries +export using ::beman::execution::forwarding_query_t; +export using ::beman::execution::get_allocator_t; +export using ::beman::execution::get_stop_token_t; + +export using ::beman::execution::forwarding_query; +export using ::beman::execution::get_allocator; +export using ::beman::execution::get_stop_token; + +export using ::beman::execution::stop_token_of_t; + +export using ::beman::execution::get_domain_t; +export using ::beman::execution::get_scheduler_t; +export using ::beman::execution::get_delegation_scheduler_t; +//-dk:TODO export using ::beman::execution::get_forward_progress_guarantee_t; +export using ::beman::execution::get_completion_scheduler_t; + +export using ::beman::execution::get_domain; +export using ::beman::execution::get_scheduler; +export using ::beman::execution::get_delegation_scheduler; +//-dk:TODO export using ::beman::execution::forward_progress_guarantee; +//-dk:TODO export using ::beman::execution::get_forward_progress_guarantee; +export using ::beman::execution::get_completion_scheduler; + +export using ::beman::execution::env; +export using ::beman::execution::get_env_t; +export using ::beman::execution::get_env; + +export using ::beman::execution::env_of_t; + +// [exec.domain.default], execution_domains +export using ::beman::execution::default_domain; + +// [exec.sched], schedulers +export using ::beman::execution::scheduler_t; +export using ::beman::execution::scheduler; + +// [exec.recv], receivers +export using ::beman::execution::receiver_t; +export using ::beman::execution::receiver; +export using ::beman::execution::receiver_of; + +export using ::beman::execution::set_value_t; +export using ::beman::execution::set_error_t; +export using ::beman::execution::set_stopped_t; + +export using ::beman::execution::set_value; +export using ::beman::execution::set_error; +export using ::beman::execution::set_stopped; + +// [exec.opstate], operation states +export using ::beman::execution::operation_state_t; +export using ::beman::execution::operation_state; +export using ::beman::execution::start_t; +export using ::beman::execution::start; + +// [exec.snd], senders +export using ::beman::execution::sender_t; +export using ::beman::execution::sender; +export using ::beman::execution::sender_in; +//-dk:TODO export using ::beman::execution::sender_to; + +// [exec.getcomplsigs], completion signatures +export using ::beman::execution::get_completion_signatures_t; +export using ::beman::execution::get_completion_signatures; +export using ::beman::execution::completion_signatures_of_t; +export using ::beman::execution::value_types_of_t; +export using ::beman::execution::error_types_of_t; +export using ::beman::execution::sends_stopped; +export using ::beman::execution::tag_of_t; + +// [exec.snd.transform], sender transformations +export using ::beman::execution::transform_sender; + +// [exec.snd.transform.env], environment transformations +//-dk:TODO export using ::beman::execution::transform_env; + +// [exec.snd.apply], sender algorithm application +export using ::beman::execution::apply_sender; + +// [exec.connect], the connect sender algorithm +export using ::beman::execution::connect_t; +export using ::beman::execution::connect; +export using ::beman::execution::connect_result_t; + +// [exec.factories], sender factories +export using ::beman::execution::just_t; +export using ::beman::execution::just_error_t; +export using ::beman::execution::just_stopped_t; +export using ::beman::execution::schedule_t; + +export using ::beman::execution::just; +export using ::beman::execution::just_error; +export using ::beman::execution::just_stopped; +export using ::beman::execution::schedule; +export using ::beman::execution::read_env; + +export using ::beman::execution::schedule_result_t; + +// [exec.adapt], sender adaptors +export using ::beman::execution::sender_adaptor_closure; + +export using ::beman::execution::starts_on_t; +export using ::beman::execution::continues_on_t; +export using ::beman::execution::on_t; +export using ::beman::execution::schedule_from_t; +export using ::beman::execution::then_t; +export using ::beman::execution::upon_error_t; +export using ::beman::execution::upon_stopped_t; +export using ::beman::execution::let_value_t; +export using ::beman::execution::let_error_t; +export using ::beman::execution::let_stopped_t; +export using ::beman::execution::bulk_t; +export using ::beman::execution::split_t; +export using ::beman::execution::when_all_t; +export using ::beman::execution::when_all_with_variant_t; +export using ::beman::execution::into_variant_t; +//-dk:TODO export using ::beman::execution::stopped_as_optional_t; +//-dk:TODO export using ::beman::execution::stopped_as_error_t; + +export using ::beman::execution::starts_on; +export using ::beman::execution::continues_on; +export using ::beman::execution::on; +export using ::beman::execution::schedule_from; +export using ::beman::execution::then; +export using ::beman::execution::upon_error; +export using ::beman::execution::upon_stopped; +export using ::beman::execution::let_value; +export using ::beman::execution::let_error; +export using ::beman::execution::let_stopped; +export using ::beman::execution::bulk; +export using ::beman::execution::split; +export using ::beman::execution::when_all; +export using ::beman::execution::when_all_with_variant; +export using ::beman::execution::into_variant; +//-dk:TODO export using ::beman::execution::stopped_as_optional; +//-dk:TODO export using ::beman::execution::stopped_as_error; + +// [exec.util.cmplsig] +export using ::beman::execution::completion_signatures; + +// [exec.util.cmplsig.trans] +//-dk:TODO export using ::beman::execution::transform_completion_signatures; +//-dk:TODO export using ::beman::execution::transform_completion_signatures_of; + +// [exec.run.loop], run_loop +export using ::beman::execution::run_loop; + +// [exec.consumers], consumers +export using ::beman::execution::sync_wait_t; +//-dk:TODO export using ::beman::execution::sync_wait_with_variant_t; + +export using ::beman::execution::sync_wait; +//-dk:TODO export using ::beman::execution::sync_wait_with_variant; + +// [exec.as.awaitable] +export using ::beman::execution::as_awaitable_t; +export using ::beman::execution::as_awaitable; + +// [exec.with.awaitable.senders] +export using ::beman::execution::with_awaitable_senders; + +//-dk:TODO add section +export using ::beman::execution::prop; +export using ::beman::execution::write_env_t; +export using ::beman::execution::write_env; +export using ::beman::execution::affine_on_t; +export using ::beman::execution::affine_on; +export using ::beman::execution::read_env_t; +export using ::beman::execution::read_env; +export using ::beman::execution::simple_counting_scope; +export using ::beman::execution::counting_scope; +export using ::beman::execution::scope_token; + +namespace detail { +export using ::beman::execution::detail::basic_sender; +export using ::beman::execution::detail::product_type; +export using ::beman::execution::detail::product_type_base; +export using ::beman::execution::detail::is_product_type_c; +export using ::beman::execution::detail::env_promise; +export using ::beman::execution::detail::await_result_type; +export using ::beman::execution::detail::simple_allocator; +export using ::beman::execution::detail::sync_wait_env; +export using ::beman::execution::detail::sync_wait_result_type; +export using ::beman::execution::detail::sync_wait_state; +export using ::beman::execution::detail::sync_wait_receiver; +export using ::beman::execution::detail::connect_all_t; +export using ::beman::execution::detail::connect_all; +} // namespace detail -template -struct product_type : ::beman::execution::detail::product_type_base<::std::index_sequence_for, T...> { - template - static auto make_from(Allocator&& allocator, Product&& product, std::index_sequence) -> product_type { - return {product_type::template make_element(allocator, ::std::forward(product))...}; - } -#line 81 "include/beman/execution/detail/product_type.hpp" - template - static auto make_from(Allocator&& allocator, Product&& product) -> product_type { - return product_type::make_from( - ::std::forward(allocator), ::std::forward(product), ::std::index_sequence_for{}); - } -#line 87 "include/beman/execution/detail/product_type.hpp" - template - constexpr auto apply_elements(::std::index_sequence, Fun&& fun) const -> decltype(auto) { - return ::std::forward(fun)(this->template get()...); - } - template - constexpr auto apply(Fun&& fun) const -> decltype(auto) { - return apply_elements(::std::index_sequence_for{}, ::std::forward(fun)); - } - template - constexpr auto apply_elements(::std::index_sequence, Fun&& fun) -> decltype(auto) { - - return ::std::forward(fun)(std::move(this->template get())...); - } - template - constexpr auto apply(Fun&& fun) -> decltype(auto) { - return apply_elements(::std::index_sequence_for{}, ::std::forward(fun)); - } -}; -template -product_type(T&&...) -> product_type<::std::decay_t...>; - -template -constexpr auto is_product_type(const T&) -> ::std::false_type { - return {}; -} -template -constexpr auto is_product_type(const ::beman::execution::detail::product_type&) -> ::std::true_type { - return {}; -} -#line 117 "include/beman/execution/detail/product_type.hpp" -template <::std::size_t Start, typename Fun, typename Tuple, ::std::size_t... I> -constexpr auto sub_apply_helper(Fun&& fun, Tuple&& tuple, ::std::index_sequence) -> decltype(auto) { - // NOLINTNEXTLINE(bugprone-use-after-move,hicpp-invalid-access-moved) - return ::std::forward(fun)(::std::forward(tuple).template get()...); -} -#line 123 "include/beman/execution/detail/product_type.hpp" -template <::std::size_t Start, typename Fun, typename Tuple> -constexpr auto sub_apply(Fun&& fun, Tuple&& tuple) -> decltype(auto) { - constexpr ::std::size_t TSize{::std::tuple_size_v<::std::remove_cvref_t>}; - static_assert(Start <= TSize); - return sub_apply_helper( - ::std::forward(fun), ::std::forward(tuple), ::std::make_index_sequence()); -} -#line 131 "include/beman/execution/detail/product_type.hpp" -} // namespace beman::execution::detail +} // namespace beman::execution namespace std { -template +export template requires ::beman::execution::detail::is_product_type_c -struct tuple_size : ::std::integral_constant {}; +struct tuple_size; -template <::std::size_t I, typename T> +export template <::std::size_t I, typename T> requires ::beman::execution::detail::is_product_type_c -struct tuple_element { - using type = ::std::decay_t().template get())>; -}; +struct tuple_element; } // namespace std - -#line 12 "include/beman/execution/detail/query_with_default.hpp" -namespace beman::execution::detail { -template - requires requires(const Tag& tag, const Env& env) { tag(env); } -constexpr auto query_with_default(Tag, const Env& env, Value&&) noexcept(noexcept(Tag()(env))) -> decltype(auto) { - return Tag()(env); -} -#line 19 "include/beman/execution/detail/query_with_default.hpp" -template -constexpr auto -query_with_default(Tag, const Env&, Value&& value) noexcept(noexcept(static_cast(std::forward(value)))) - -> decltype(auto) { - return static_cast(std::forward(value)); -} -} // namespace beman::execution::detail - -#line 13 "include/beman/execution/detail/child_type.hpp" -namespace beman::execution::detail { - -#line 19 "include/beman/execution/detail/child_type.hpp" -template -using child_type = decltype(::std::declval().template get()); -} // namespace beman::execution::detail - -#line 13 "include/beman/execution/detail/decayed_tuple.hpp" -namespace beman::execution::detail { - -#line 19 "include/beman/execution/detail/decayed_tuple.hpp" -template -using decayed_tuple = ::std::tuple<::std::decay_t...>; -} // namespace beman::execution::detail - -#line 13 "include/beman/execution/detail/make_env.hpp" -namespace beman::execution::detail { -export /* --------- */ template -class make_env { - private: - Value value; - - public: - template - make_env(const Query&, V&& v) : value(::std::forward(v)) {} - constexpr auto query(const Query&) const noexcept -> const Value& { return this->value; } - constexpr auto query(const Query&) noexcept -> Value& { return this->value; } -}; -template -make_env(Query&&, Value&& value) -> make_env<::std::remove_cvref_t, ::std::remove_cvref_t>; -} // namespace beman::execution::detail - -#line 11 "include/beman/execution/detail/meta_prepend.hpp" -namespace beman::execution::detail::meta::detail { -template -struct prepend; - -template