diff --git a/include/exec/detail/basic_sequence.hpp b/include/exec/detail/basic_sequence.hpp index 2c4a92b38..0357b7a0c 100644 --- a/include/exec/detail/basic_sequence.hpp +++ b/include/exec/detail/basic_sequence.hpp @@ -127,6 +127,6 @@ namespace STDEXEC::__detail extern decltype(_DescriptorFn()) __desc_of_v>; template - extern __declfn_t<__minvoke>> + extern __mtype<__minvoke>> __demangle_v>; } // namespace STDEXEC::__detail diff --git a/include/exec/repeat_until.hpp b/include/exec/repeat_until.hpp index c44b36645..13b18f3cf 100644 --- a/include/exec/repeat_until.hpp +++ b/include/exec/repeat_until.hpp @@ -275,8 +275,8 @@ namespace experimental::execution using __eptr_completion_t = set_error_t(std::exception_ptr); constexpr auto __eptr_completion = (__eptr_completion_t *) nullptr; - STDEXEC_COMPLSIGS_LET( - __sigs, + STDEXEC_TRY_LET( + auto __sigs, exec::transform_completion_signatures(get_completion_signatures<__child_t, _Env...>(), __transform_values<__child_t>, __transform_errors)) diff --git a/include/exec/static_thread_pool.hpp b/include/exec/static_thread_pool.hpp index 582f91b12..6673cc619 100644 --- a/include/exec/static_thread_pool.hpp +++ b/include/exec/static_thread_pool.hpp @@ -45,7 +45,6 @@ #include "sequence/iterate.hpp" #include "sequence_senders.hpp" -#include #include #include #include diff --git a/include/nvexec/nvtx.cuh b/include/nvexec/nvtx.cuh index 0c5bd4de2..d0be24e8b 100644 --- a/include/nvexec/nvtx.cuh +++ b/include/nvexec/nvtx.cuh @@ -196,7 +196,7 @@ namespace nvexec = nv::execution; namespace STDEXEC::__detail { template - extern __declfn_t>> + extern __mtype>> __demangle_v>; } // namespace STDEXEC::__detail diff --git a/include/nvexec/stream/algorithm_base.cuh b/include/nvexec/stream/algorithm_base.cuh index c5b6a54ab..8832c1a84 100644 --- a/include/nvexec/stream/algorithm_base.cuh +++ b/include/nvexec/stream/algorithm_base.cuh @@ -145,7 +145,7 @@ namespace nvexec = nv::execution; namespace STDEXEC::__detail { template - extern __declfn_t, InitT, Fun, __demangle_t>> + extern __mtype, InitT, Fun, __demangle_t>> __demangle_v>; } // namespace STDEXEC::__detail diff --git a/include/nvexec/stream/bulk.cuh b/include/nvexec/stream/bulk.cuh index e8b277ab2..a3a2a6ab8 100644 --- a/include/nvexec/stream/bulk.cuh +++ b/include/nvexec/stream/bulk.cuh @@ -440,12 +440,11 @@ namespace nvexec = nv::execution; namespace STDEXEC::__detail { template - inline constexpr __declfn_t, Shape, Fun>> + inline constexpr __mtype, Shape, Fun>> __demangle_v>{}; template - inline constexpr __declfn_t< - nvexec::_strm::multi_gpu_bulk_sender<__demangle_t, Shape, Fun>> + inline constexpr __mtype, Shape, Fun>> __demangle_v>{}; } // namespace STDEXEC::__detail diff --git a/include/nvexec/stream/continues_on.cuh b/include/nvexec/stream/continues_on.cuh index a7ee8f260..b06697755 100644 --- a/include/nvexec/stream/continues_on.cuh +++ b/include/nvexec/stream/continues_on.cuh @@ -284,7 +284,7 @@ namespace nvexec = nv::execution; namespace STDEXEC::__detail { template - extern __declfn_t>> + extern __mtype>> __demangle_v>; } // namespace STDEXEC::__detail diff --git a/include/nvexec/stream/ensure_started.cuh b/include/nvexec/stream/ensure_started.cuh index 324842cd2..30ae50ab4 100644 --- a/include/nvexec/stream/ensure_started.cuh +++ b/include/nvexec/stream/ensure_started.cuh @@ -430,7 +430,7 @@ namespace nvexec = nv::execution; namespace STDEXEC::__detail { template - extern __declfn_t>> + extern __mtype>> __demangle_v>; } // namespace STDEXEC::__detail diff --git a/include/nvexec/stream/launch.cuh b/include/nvexec/stream/launch.cuh index 35b29e785..de3f79f1d 100644 --- a/include/nvexec/stream/launch.cuh +++ b/include/nvexec/stream/launch.cuh @@ -204,7 +204,7 @@ namespace nvexec = nv::execution; namespace STDEXEC::__detail { template - extern __declfn_t, Fun>> + extern __mtype, Fun>> __demangle_v>; } // namespace STDEXEC::__detail diff --git a/include/nvexec/stream/let_xxx.cuh b/include/nvexec/stream/let_xxx.cuh index 4d7e3b940..0ed840cb5 100644 --- a/include/nvexec/stream/let_xxx.cuh +++ b/include/nvexec/stream/let_xxx.cuh @@ -344,7 +344,7 @@ namespace nvexec = nv::execution; namespace STDEXEC::__detail { template - extern __declfn_t, Fun, SetTag>> + extern __mtype, Fun, SetTag>> __demangle_v>; } // namespace STDEXEC::__detail diff --git a/include/nvexec/stream/reduce.cuh b/include/nvexec/stream/reduce.cuh index 90a5c3780..b1ec38b56 100644 --- a/include/nvexec/stream/reduce.cuh +++ b/include/nvexec/stream/reduce.cuh @@ -165,7 +165,7 @@ namespace nvexec = nv::execution; namespace STDEXEC::__detail { template - extern __declfn_t, Init, Fun>> + extern __mtype, Init, Fun>> __demangle_v>; } // namespace STDEXEC::__detail diff --git a/include/nvexec/stream/schedule_from.cuh b/include/nvexec/stream/schedule_from.cuh index cb979c650..8f7edee11 100644 --- a/include/nvexec/stream/schedule_from.cuh +++ b/include/nvexec/stream/schedule_from.cuh @@ -196,6 +196,6 @@ namespace nvexec = nv::execution; namespace STDEXEC::__detail { template - extern __declfn_t>> + extern __mtype>> __demangle_v>; } // namespace STDEXEC::__detail diff --git a/include/nvexec/stream/split.cuh b/include/nvexec/stream/split.cuh index 7488cbb39..d461e3ff1 100644 --- a/include/nvexec/stream/split.cuh +++ b/include/nvexec/stream/split.cuh @@ -412,7 +412,7 @@ namespace nvexec = nv::execution; namespace STDEXEC::__detail { template - extern __declfn_t>> + extern __mtype>> __demangle_v>; } // namespace STDEXEC::__detail diff --git a/include/nvexec/stream/then.cuh b/include/nvexec/stream/then.cuh index 9d8f0171c..44e3a53b7 100644 --- a/include/nvexec/stream/then.cuh +++ b/include/nvexec/stream/then.cuh @@ -228,7 +228,7 @@ namespace nvexec = nv::execution; namespace STDEXEC::__detail { template - extern __declfn_t, Fun>> + extern __mtype, Fun>> __demangle_v>; } // namespace STDEXEC::__detail diff --git a/include/nvexec/stream/upon_error.cuh b/include/nvexec/stream/upon_error.cuh index 4f0904f1a..38350b9ff 100644 --- a/include/nvexec/stream/upon_error.cuh +++ b/include/nvexec/stream/upon_error.cuh @@ -216,7 +216,7 @@ namespace nvexec = nv::execution; namespace STDEXEC::__detail { template - extern __declfn_t, Fun>> + extern __mtype, Fun>> __demangle_v>; } // namespace STDEXEC::__detail diff --git a/include/nvexec/stream/upon_stopped.cuh b/include/nvexec/stream/upon_stopped.cuh index f18e4a120..cb7668c59 100644 --- a/include/nvexec/stream/upon_stopped.cuh +++ b/include/nvexec/stream/upon_stopped.cuh @@ -207,7 +207,7 @@ namespace nvexec = nv::execution; namespace STDEXEC::__detail { template - extern __declfn_t, Fun>> + extern __mtype, Fun>> __demangle_v>; } // namespace STDEXEC::__detail diff --git a/include/nvexec/stream/when_all.cuh b/include/nvexec/stream/when_all.cuh index a367a9653..efa005e18 100644 --- a/include/nvexec/stream/when_all.cuh +++ b/include/nvexec/stream/when_all.cuh @@ -576,7 +576,7 @@ namespace nvexec = nv::execution; namespace STDEXEC::__detail { template - extern __declfn_t...>> + extern __mtype...>> __demangle_v>; } // namespace STDEXEC::__detail diff --git a/include/stdexec/__detail/__basic_sender.hpp b/include/stdexec/__detail/__basic_sender.hpp index 1f987463a..44fdf8a6b 100644 --- a/include/stdexec/__detail/__basic_sender.hpp +++ b/include/stdexec/__detail/__basic_sender.hpp @@ -456,7 +456,7 @@ namespace STDEXEC using __basic_sender_t = __basic_sender<_Tag, _Data, __demangle_t<_Child>...>::type; template - extern __declfn_t<__minvoke>> + extern __mtype<__minvoke>> __demangle_v<__sexpr<_Descriptor>>; } // namespace __detail } // namespace STDEXEC diff --git a/include/stdexec/__detail/__completion_info.hpp b/include/stdexec/__detail/__completion_info.hpp new file mode 100644 index 000000000..cef76b289 --- /dev/null +++ b/include/stdexec/__detail/__completion_info.hpp @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2026 NVIDIA Corporation + * + * Licensed under the Apache License Version 2.0 with LLVM Exceptions + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://llvm.org/LICENSE.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include "__execution_fwd.hpp" + +// IWYU pragma: begin_keep +#include "__completion_behavior.hpp" +#include "__completion_signatures.hpp" +#include "__meta.hpp" +#include "__static_vector.hpp" +#include "__typeinfo.hpp" + +#include "../functional.hpp" + +#include +#include +#include +#include +#include +// IWYU pragma: end_keep + +namespace STDEXEC +{ + template + constexpr _Sig *__signature = nullptr; + + struct __completion_info + { + using __behavior_t = __completion_behavior::__behavior; + + STDEXEC::__disposition __disposition = __invalid_disposition; + __type_index __signature = __mtypeid; + __type_index __domain = __mtypeid; + __behavior_t __behavior = __completion_behavior::__unknown; + + __completion_info() = default; + + template <__completion_tag _Tag, class... _Args> + constexpr __completion_info(_Tag (*)(_Args...), + __type_index __domain = __mtypeid, + __behavior_t __behavior = __completion_behavior::__unknown) noexcept + : __disposition(_Tag::__disposition) + , __signature(__mtypeid<_Tag(_Args...)>) + , __domain(__domain) + , __behavior(__behavior) + {} + + template + constexpr auto __populate() noexcept -> __completion_info & + { + switch (__disposition) + { + case __disposition::__value: + __domain = __mtypeid<__completion_domain_t, _Env...>>; + __behavior = STDEXEC::__get_completion_behavior(); + break; + case __disposition::__error: + __domain = __mtypeid<__completion_domain_t, _Env...>>; + __behavior = STDEXEC::__get_completion_behavior(); + break; + case __disposition::__stopped: + __domain = __mtypeid<__completion_domain_t, _Env...>>; + __behavior = STDEXEC::__get_completion_behavior(); + break; + } + return *this; + } + + [[nodiscard]] + constexpr auto + operator<=>(__completion_info const &) const noexcept -> std::strong_ordering = default; + }; + + namespace __cmplsigs + { + template + constexpr auto __completion_info_from_v = []() noexcept + { + STDEXEC_TRY_LET(auto __cmpl_info, _GetComplInfo()) + { + constexpr auto __size = _GetComplInfo().size(); + auto __arr = __static_vector<__completion_info, __size>(); + std::ranges::sort(__cmpl_info); + auto const __end = std::ranges::unique_copy(__cmpl_info, __arr.begin()).out; + __arr.resize(__end - __arr.begin()); + return __arr; + } + }(); + + template + consteval auto __completion_info_from(_GetComplInfo) noexcept -> auto const & + { + return __completion_info_from_v<(_GetComplInfo())>; + } + + template + constexpr auto __completion_sigs_from_v = []() noexcept + { + STDEXEC_TRY_LET(constexpr auto __completions, __completion_info_from_v<_GetComplInfo>) + { + auto __signatures = __static_vector<__type_index, __completions.size()>(); + __signatures.resize(__completions.size()); + std::ranges::transform(__completions, + __signatures.begin(), + &__completion_info::__signature); + auto const __end = std::ranges::unique(__signatures).begin(); + __signatures.resize(__end - __signatures.begin()); + return __signatures; + } + }(); + + template + consteval auto __completion_sigs_from(_GetComplInfo) noexcept + { + STDEXEC_TRY_LET(constexpr auto __sigs, __completion_sigs_from_v<(_GetComplInfo())>) + { + constexpr auto __fn = [=](__indices<_Is...>) + { + return completion_signatures<__mtypeof<__sigs[_Is]>...>(); + }; + return __fn(__make_indices<__sigs.size()>()); + } + } + + template + [[nodiscard]] + consteval auto __to_array(completion_signatures<_Sigs...>) noexcept + { + using __array_t = __static_vector<__completion_info, sizeof...(_Sigs)>; + auto __compls = __array_t{__completion_info(__signature<_Sigs>)...}; + std::ranges::sort(__compls); + return __compls; + } + + template + constexpr auto __append_range(std::vector<_Ty> &__dst, std::span<_Ty const> __src) + { + #if __cpp_lib_containers_ranges >= 202202L + __dst.append_range(__src); + #else + __dst.insert(__dst.end(), __src.begin(), __src.end()); + #endif + } + } // namespace __cmplsigs +} // namespace STDEXEC diff --git a/include/stdexec/__detail/__completion_signatures.hpp b/include/stdexec/__detail/__completion_signatures.hpp index 2d6fd54b9..cbf612bec 100644 --- a/include/stdexec/__detail/__completion_signatures.hpp +++ b/include/stdexec/__detail/__completion_signatures.hpp @@ -541,38 +541,50 @@ namespace STDEXEC __cmplsigs::__partitions_of_t<_Sigs>::__count_stopped::value; } // namespace __detail - // Below is the definition of the STDEXEC_COMPLSIGS_LET portability macro. It - // is used to check that an expression's type is a valid completion_signature - // specialization. + // Below is the definition of the STDEXEC_TRY_LET portability macro. It is used to check + // that an expression's type is not an __mexception type. // // USAGE: // - // STDEXEC_COMPLSIGS_LET(__cs, ) + // STDEXEC_TRY_LET([constexpr]opt auto c, ) // { - // // __cs is guaranteed to be a specialization of completion_signatures. + // // c is guaranteed to not be an instantiation of __mexception. // } // - // When constexpr exceptions are available (C++26), the macro simply expands to - // the moral equivalent of: + // When constexpr exceptions are available (C++26), the macro simply expands to the + // moral equivalent of: // // // With constexpr exceptions: - // auto __cs = ; // throws if __cs is not a completion_signatures + // auto c = ; // throws if c is an __mexception type // // When constexpr exceptions are not available, the macro expands to: // // // Without constexpr exceptions: - // if constexpr (auto __cs = ; !__valid_completion_signatures) + // if constexpr (auto c = ; __merror) // { - // return __cs; + // return c; // } // else #if STDEXEC_NO_STDCPP_CONSTEXPR_EXCEPTIONS() -# define STDEXEC_COMPLSIGS_LET(_ID, ...) \ - if constexpr ([[maybe_unused]] auto _ID = __VA_ARGS__; \ - !STDEXEC::__valid_completion_signatures) { \ - return _ID; \ +# define STDEXEC_EAT_AUTO_auto +# define STDEXEC_EAT_CONSTEXPR_constexpr +# define STDEXEC_EAT_CONSTEXPR(_ID) STDEXEC_EAT_CONSTEXPR_ ## _ID + +# define STDEXEC_PROBE_CONSTEXPR_constexpr STDEXEC_PP_PROBE(~, 1) +# define STDEXEC_TRY_LET_ID(_ID) \ + STDEXEC_PP_CAT( \ + STDEXEC_EAT_AUTO_, \ + STDEXEC_PP_IIF( \ + STDEXEC_PP_CHECK(STDEXEC_PROBE_CONSTEXPR_ ## _ID), \ + STDEXEC_EAT_CONSTEXPR, \ + STDEXEC_PP_EXPAND)(_ID)) + +# define STDEXEC_TRY_LET(_ID, ...) \ + if constexpr ([[maybe_unused]] _ID = __VA_ARGS__; __merror) \ + { \ + return STDEXEC_TRY_LET_ID(_ID); \ } else template @@ -591,8 +603,9 @@ namespace STDEXEC #else // ^^^ no constexpr exceptions ^^^ / vvv constexpr exceptions vvv -# define STDEXEC_COMPLSIGS_LET(_ID, ...) \ - if constexpr ([[maybe_unused]] auto _ID = __VA_ARGS__; false) { \ +# define STDEXEC_TRY_LET(_ID, ...) \ + if constexpr ([[maybe_unused]] _ID = __VA_ARGS__; false) \ + { \ } else template diff --git a/include/stdexec/__detail/__concepts.hpp b/include/stdexec/__detail/__concepts.hpp index f4de37fb1..21e235857 100644 --- a/include/stdexec/__detail/__concepts.hpp +++ b/include/stdexec/__detail/__concepts.hpp @@ -252,6 +252,16 @@ namespace STDEXEC } // namespace __std + template + concept __initializable_from = requires(__declfn_t<_As &&>... __as) { + { _Ty{__as()...} }; + }; + + template + concept __nothrow_initializable_from = requires(__declfn_t<_As &&>... __as) { + { _Ty{__as()...} } noexcept; + }; + template concept __movable_value = __std::move_constructible<__decay_t<_Ty>> && __std::constructible_from<__decay_t<_Ty>, _Ty>; diff --git a/include/stdexec/__detail/__continues_on.hpp b/include/stdexec/__detail/__continues_on.hpp index b87c400f8..e0498c53c 100644 --- a/include/stdexec/__detail/__continues_on.hpp +++ b/include/stdexec/__detail/__continues_on.hpp @@ -318,8 +318,8 @@ namespace STDEXEC template static consteval auto __get_child_completions() { - STDEXEC_COMPLSIGS_LET(__child_completions, - STDEXEC::get_completion_signatures<_Child, __fwd_env_t<_Env>...>()) + STDEXEC_TRY_LET(auto __child_completions, + STDEXEC::get_completion_signatures<_Child, __fwd_env_t<_Env>...>()) { // continues_on has the completions of the child sender, but with value and // error result types decayed. @@ -334,8 +334,8 @@ namespace STDEXEC static consteval auto __get_scheduler_completions() { using __sndr_t = schedule_result_t<_Scheduler>; - STDEXEC_COMPLSIGS_LET(__sched_completions, - STDEXEC::get_completion_signatures<__sndr_t, __fwd_env_t<_Env>...>()) + STDEXEC_TRY_LET(auto __sched_completions, + STDEXEC::get_completion_signatures<__sndr_t, __fwd_env_t<_Env>...>()) { // The scheduler contributes only error and stopped completions; we ignore value // completions here diff --git a/include/stdexec/__detail/__cpo.hpp b/include/stdexec/__detail/__cpo.hpp deleted file mode 100644 index bbe2ae8b4..000000000 --- a/include/stdexec/__detail/__cpo.hpp +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2024 NVIDIA Corporation - * - * Licensed under the Apache License Version 2.0 with LLVM Exceptions - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * https://llvm.org/LICENSE.txt - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#pragma once - -#include "__config.hpp" -#include "__execution_fwd.hpp" - -#if STDEXEC_MSVC() -# pragma deprecated(STDEXEC_CUSTOM) -# pragma deprecated(STDEXEC_MEMFN_DECL) -#endif - -/////////////////////////////////////////////////////////////////////////////// -/// To hook a customization point like STDEXEC::get_env, first bring the names -/// in STDEXEC::tags into scope: -/// -/// @code -/// using namespace STDEXEC::tags; -/// @endcode -/// -/// Then define a member function like this: -/// -/// @code -/// STDEXEC_MEMFN_DECL(auto get_env)(this const MySender& self) { -/// return ...; -/// } -/// @endcode -#define STDEXEC_MEMFN_DECL_IMPL(...) \ - friend STDEXEC_PP_EVAL( \ - STDEXEC_MEMFN_DECL_TAG_INVOKE, STDEXEC_MEMFN_DECL_WHICH(__VA_ARGS__), __VA_ARGS__) - -#define STDEXEC_MEMFN_DECL_WHICH(_A1, ...) \ - STDEXEC_PP_CAT(STDEXEC_MEMFN_DECL_WHICH_, STDEXEC_PP_FRONT(__VA_OPT__(1, ) 0))(_A1, __VA_ARGS__) -#define STDEXEC_MEMFN_DECL_WHICH_0(_A1, ...) \ - STDEXEC_PP_CHECK(STDEXEC_MEMFN_DECL_PROBE_##_A1), STDEXEC_PP_CHECK(_A1##_STDEXEC_MEMFN_DECL_PROBE) -#define STDEXEC_MEMFN_DECL_WHICH_1(_A1, ...) \ - 0, STDEXEC_PP_CHECK(STDEXEC_PP_CAT(STDEXEC_PP_BACK(__VA_ARGS__), _STDEXEC_MEMFN_DECL_PROBE)) - -#define STDEXEC_MEMFN_DECL_TAG_INVOKE(_WHICH, _QUERY, ...) \ - STDEXEC_MEMFN_DECL_RETURN_ ## _WHICH(__VA_ARGS__) \ - __tag_invoke(STDEXEC_MEMFN_DECL_TAG_ ## _WHICH ## _QUERY(__VA_ARGS__) - -#define STDEXEC_MEMFN_DECL_ARGS(...) \ - STDEXEC_PP_CAT(STDEXEC_EAT_THIS_, __VA_ARGS__)) - -#define STDEXEC_MEMFN_DECL_QUERY(_SELF, _TAG, ...) \ - _TAG, STDEXEC_PP_CAT(STDEXEC_EAT_THIS_, _SELF) __VA_OPT__(, __VA_ARGS__)) - -#define STDEXEC_EAT_THIS_this -#define STDEXEC_EAT_AUTO_auto -#define STDEXEC_EAT_VOID_void - -#define query_STDEXEC_MEMFN_DECL_PROBE STDEXEC_PP_PROBE(~, 1) -#define STDEXEC_MEMFN_DECL_PROBE_auto STDEXEC_PP_PROBE(~, 1) -#define STDEXEC_MEMFN_DECL_PROBE_void STDEXEC_PP_PROBE(~, 2) - -#define STDEXEC_MEMFN_DECL_RETURN_0(...) ::STDEXEC::__arg_type_t -#define STDEXEC_MEMFN_DECL_RETURN_1(...) auto -#define STDEXEC_MEMFN_DECL_RETURN_2(...) void - -#define STDEXEC_MEMFN_DECL_TAG_00(...) \ - const ::STDEXEC::__tag_type_t<__VA_ARGS__##_t::*>&, STDEXEC_MEMFN_DECL_ARGS -#define STDEXEC_MEMFN_DECL_TAG_10(...) \ - const STDEXEC_EAT_AUTO_##__VA_ARGS__##_t&, STDEXEC_MEMFN_DECL_ARGS -#define STDEXEC_MEMFN_DECL_TAG_20(...) \ - const STDEXEC_EAT_VOID_##__VA_ARGS__##_t&, STDEXEC_MEMFN_DECL_ARGS -#define STDEXEC_MEMFN_DECL_TAG_01(...) STDEXEC_MEMFN_DECL_QUERY -#define STDEXEC_MEMFN_DECL_TAG_11(...) STDEXEC_MEMFN_DECL_QUERY -#define STDEXEC_MEMFN_DECL_TAG_21(...) STDEXEC_MEMFN_DECL_QUERY - -#define STDEXEC_MEMFN_FRIEND(_TAG) \ - using STDEXEC_PP_CAT(_TAG, _t) = STDEXEC_PP_CAT(STDEXEC::_TAG, _t) - -#if STDEXEC_GCC() || (STDEXEC_CLANG() && STDEXEC_CLANG_VERSION < 1400) -# define STDEXEC_CUSTOM \ - _Pragma("GCC warning \"STDEXEC_CUSTOM is deprecated.\"") STDEXEC_MEMFN_DECL_IMPL -# define STDEXEC_MEMFN_DECL \ - _Pragma("GCC warning \"STDEXEC_MEMFN_DECL is deprecated.\"") STDEXEC_MEMFN_DECL_IMPL -#else -# define STDEXEC_CUSTOM STDEXEC_MEMFN_DECL_IMPL -# define STDEXEC_MEMFN_DECL STDEXEC_MEMFN_DECL_IMPL -#endif - -#if STDEXEC_CLANG() && STDEXEC_CLANG_VERSION >= 1400 -# pragma clang deprecated(STDEXEC_CUSTOM) -# pragma clang deprecated(STDEXEC_MEMFN_DECL) -#endif - -namespace STDEXEC -{ - template - struct __arg_type; - - template - struct __arg_type - { - using type = _Arg; - }; - - template - using __arg_type_t = __arg_type<_Fn>::type; - - template - struct __tag_type; - - template - struct __tag_type<_Ret _Tag::*> - { - using type = _Tag; - }; - - template - using __tag_type_t = __tag_type<_Fn>::type; - - namespace tags - { - using STDEXEC::set_value_t; - using STDEXEC::set_error_t; - using STDEXEC::set_stopped_t; - using STDEXEC::connect_t; - using STDEXEC::start_t; - using STDEXEC::get_env_t; - using STDEXEC::get_completion_signatures_t; - } // namespace tags -} // namespace STDEXEC diff --git a/include/stdexec/__detail/__diagnostics.hpp b/include/stdexec/__detail/__diagnostics.hpp index 485a67625..fe2f67bf6 100644 --- a/include/stdexec/__detail/__diagnostics.hpp +++ b/include/stdexec/__detail/__diagnostics.hpp @@ -267,15 +267,22 @@ namespace STDEXEC "complete."} {} - STDEXEC_ATTRIBUTE(host, device) constexpr auto operator+() const -> _ERROR_; + STDEXEC_ATTRIBUTE(host, device) + constexpr auto operator+() const -> _ERROR_; template STDEXEC_ATTRIBUTE(host, device) - constexpr auto operator,(_Ty const &) const -> _ERROR_; + constexpr auto operator,(_Ty const &) const -> _ERROR_ + { + return *this; + } template STDEXEC_ATTRIBUTE(host, device) - constexpr auto operator,(const _ERROR_ &) const -> _ERROR_; + constexpr auto operator,(const _ERROR_ &__other) const -> _ERROR_ + { + return __other; + } }; // By making __dependent_sender_error_t an alias for _ERROR_<...>, we ensure that diff --git a/include/stdexec/__detail/__domain.hpp b/include/stdexec/__detail/__domain.hpp index 2d49145c5..096671ccc 100644 --- a/include/stdexec/__detail/__domain.hpp +++ b/include/stdexec/__detail/__domain.hpp @@ -18,10 +18,8 @@ #include "__execution_fwd.hpp" #include "__completion_behavior.hpp" -#include "__completion_signatures_of.hpp" #include "__concepts.hpp" #include "__config.hpp" -#include "__execution_fwd.hpp" #include "__meta.hpp" #include "__sender_introspection.hpp" #include "__utility.hpp" @@ -171,12 +169,6 @@ namespace STDEXEC } // namespace __detail //////////////////////////////////////////////////////////////////////////////////////////////// - template - using __completion_domain_t = __call_result_or_t, - indeterminate_domain<>, - _Attrs, - _Env const &...>; - template requires __sends<_Tag, _Sender, _Env...> using __completion_domain_of_t = __completion_domain_t<_Tag, env_of_t<_Sender>, _Env const &...>; diff --git a/include/stdexec/__detail/__execution_fwd.hpp b/include/stdexec/__detail/__execution_fwd.hpp index 38e8408c7..a9892660d 100644 --- a/include/stdexec/__detail/__execution_fwd.hpp +++ b/include/stdexec/__detail/__execution_fwd.hpp @@ -74,6 +74,15 @@ namespace STDEXEC extern set_error_t const set_error; extern set_stopped_t const set_stopped; + enum class __disposition + { + __value, + __error, + __stopped + }; + + constexpr auto __invalid_disposition = static_cast<__disposition>(3); // invalid value + template concept __completion_tag = __one_of<_Tag, set_value_t, set_error_t, set_stopped_t>; @@ -135,6 +144,12 @@ namespace STDEXEC extern get_domain_t const get_domain; extern get_await_completion_adaptor_t const get_await_completion_adaptor; + template + using __completion_domain_t = __call_result_or_t, + indeterminate_domain<>, + _Attrs, + _Env const &...>; + template concept __is_debug_env = __callable<__debug_env_t, _Env>; diff --git a/include/stdexec/__detail/__finally.hpp b/include/stdexec/__detail/__finally.hpp index 45d06d572..a517d6f1c 100644 --- a/include/stdexec/__detail/__finally.hpp +++ b/include/stdexec/__detail/__finally.hpp @@ -307,12 +307,12 @@ namespace STDEXEC template consteval auto __get_completion_signatures() { - STDEXEC_COMPLSIGS_LET(__initial_completions, - get_completion_signatures<_CvInitialSender, _Env...>()) + STDEXEC_TRY_LET(auto __initial_completions, + get_completion_signatures<_CvInitialSender, _Env...>()) { using __initial_completions_t = decltype(__initial_completions); - STDEXEC_COMPLSIGS_LET( - __final_completions, + STDEXEC_TRY_LET( + auto __final_completions, get_completion_signatures<_CvFinalSender, __mk_final_env_t<_CvInitialSender, _Env>...>()) { if constexpr (__never_sends using __count_of = __msize_t<__detail::__count_of<_Tag, __completion_signatures_of_t<_Sender, _Env...>>>; + + template + consteval auto __get_cmpl_info() + { + STDEXEC_TRY_LET(auto __cmplsigs, STDEXEC::get_completion_signatures<_Sender, _Env...>()) + { + constexpr auto __cmplinfo = STDEXEC::__cmplsigs::__to_array(__cmplsigs); + auto __cmplinfo_copy = __cmplinfo; // avoid modifying the constexpr array + for (__completion_info &__cmpl: __cmplinfo_copy) + __cmpl.__populate<_Sender, _Env...>(); + return __cmplinfo_copy; + } + } } // namespace STDEXEC diff --git a/include/stdexec/__detail/__let.hpp b/include/stdexec/__detail/__let.hpp index 1c1d89fe2..c024f4c49 100644 --- a/include/stdexec/__detail/__let.hpp +++ b/include/stdexec/__detail/__let.hpp @@ -19,6 +19,7 @@ // include these after __execution_fwd.hpp #include "__basic_sender.hpp" +#include "__completion_info.hpp" #include "__diagnostics.hpp" #include "__domain.hpp" #include "__env.hpp" @@ -27,7 +28,6 @@ #include "__sender_adaptor_closure.hpp" #include "__senders.hpp" #include "__submit.hpp" -#include "__transform_completion_signatures.hpp" #include "__utility.hpp" #include "__variant.hpp" @@ -106,6 +106,12 @@ namespace STDEXEC __fn_t<_WITH_ENVIRONMENT_, _JoinEnv2>..., __mapply_q<_NESTED_ERROR_, __try_completion_signatures_of_t<_Sender, _JoinEnv2...>>>; + template + using __not_decay_copyable_error_t = + __mexception<_WHAT_(_SENDER_RESULTS_ARE_NOT_DECAY_COPYABLE_), + _WHERE_(_IN_ALGORITHM_, _LetTag), + _WITH_ARGUMENTS_(_Args...)>; + template concept __potentially_valid_sender_in = sender_in<_Sender, _JoinEnv2...> || (sender<_Sender> && (sizeof...(_JoinEnv2) == 0)); @@ -132,7 +138,8 @@ namespace STDEXEC using __rcvr2_t = __receiver_archetype<_Env2>; template - using __f = __mbool<__nothrow_decay_copyable<_Ts...> + using __f = __mbool<__nothrow_decay_copyable<_Ts...> // + && __nothrow_invocable<_Fn, __decay_t<_Ts>&...> // && __nothrow_connectable<__sndr2_t<_Ts...>, __rcvr2_t>>; }; @@ -514,111 +521,143 @@ namespace STDEXEC struct __impls : __sexpr_defaults { private: - using __set_t = __t<_LetTag>; - template - using __fn_t = __decay_t<__data_of<_Sender>>; + using __set_t = __t<_LetTag>; + using __cmpl_vec_t = std::vector<__completion_info>; + using __eptr_sig_t = set_error_t(std::exception_ptr); + + template + using __fn_t = __decay_t<__data_of<_CvSender>>; + + template + using __env2_t = __let::__result_env_t<__set_t, _CvSender, _Env>; - template + template + using __rcvr2_t = __receiver_archetype<__env2_t<_CvSender, _Env>>; + + template using __opstate_t = __gather_completions_of_t< - __t<_LetTag>, - __child_of<_Sender>, + __set_t, + __child_of<_CvSender>, __fwd_env_t>, __q<__decayed_tuple>, - __mbind_front_q<__opstate, __t<_LetTag>, __child_of<_Sender>, __fn_t<_Sender>, _Receiver>>; + __mbind_front_q<__opstate, __set_t, __child_of<_CvSender>, __fn_t<_CvSender>, _Receiver>>; - template - using __not_decay_copyable_error_t = - __mexception<_WHAT_(_SENDER_RESULTS_ARE_NOT_DECAY_COPYABLE_), - _WHERE_(_IN_ALGORITHM_, _LetTag), - _WITH_ARGUMENTS_(_Args...)>; - - public: - static constexpr auto __get_attrs = - [](__ignore, __ignore, _Child const & __child) noexcept -> decltype(auto) + template + static constexpr auto __transform_cmplsig = // + [](__set_t (*)(_As...), __completion_info __info, __cmpl_vec_t& __out) // + -> decltype(auto) { - // TODO(ericniebler): this needs a proper implementation - return __fwd_env(STDEXEC::get_env(__child)); - }; - - template - static consteval auto __get_completion_signatures() - { - static_assert(__sender_for<_CvSndr, _LetTag>); - using __fn_t = __impls::__fn_t<_CvSndr>; - using __child_t = __child_of<_CvSndr>; - auto __completions = STDEXEC::get_completion_signatures<__child_t, _Env...>(); - auto __transform_fn = []() + if constexpr (!__decay_copyable<_As...>) { - if constexpr (!__invocable<__fn_t, __decay_t<_Args>&...>) - { - using __what_t = __callable_error_t<_LetTag, __fn_t, __decay_t<_Args>&...>; - return STDEXEC::__throw_compile_time_error(__what_t()); - } - else if constexpr (!__decay_copyable<_Args...>) - { - using __what_t = __not_decay_copyable_error_t<_Args...>; - return STDEXEC::__throw_compile_time_error(__what_t()); - } - else if constexpr (!__potentially_valid_sender_in< - __invoke_result_t<__fn_t, __decay_t<_Args>&...>, - __result_env_t<__set_t, __child_t, _Env>...>) - { - using __sndr_t = __invoke_result_t<__fn_t, __decay_t<_Args>&...>; - using __what_t = - __bad_result_sender<__sndr_t, _LetTag, __result_env_t<__set_t, __child_t, _Env>...>; - return STDEXEC::__throw_compile_time_error(__what_t()); - } - else + using __what_t = __not_decay_copyable_error_t<_LetTag, _As...>; + return STDEXEC::__throw_compile_time_error(__what_t()); + } + else if constexpr (!__invocable<_Fun, __decay_t<_As>&...>) + { + using __what_t = __callable_error_t<_LetTag, _Fun, __decay_t<_As>&...>; + return STDEXEC::__throw_compile_time_error(__what_t()); + } + else if constexpr (!__potentially_valid_sender_in< + __invoke_result_t<_Fun, __decay_t<_As>&...>, + __env2_t<_Child, _Env>...>) + { + using __sndr_t = __invoke_result_t<_Fun, __decay_t<_As>&...>; + using __what_t = __bad_result_sender<__sndr_t, _LetTag, __env2_t<_Child, _Env>...>; + return STDEXEC::__throw_compile_time_error(__what_t()); + } + else + { + using __sndr2_t = __invoke_result_t<_Fun, __decay_t<_As>&...>; + STDEXEC_TRY_LET(constexpr auto __cmpls, + STDEXEC::__get_cmpl_info<__sndr2_t, __env2_t<_Child, _Env>...>()) { - using __sndr_t = __invoke_result_t<__fn_t, __decay_t<_Args>&...>; - using __nothrow_t = __mbool<__nothrow_invocable<__fn_t, __decay_t<_Args>&...> - && __nothrow_decay_copyable<_Args...>>; - - STDEXEC_COMPLSIGS_LET( - __sigs, - STDEXEC::__concat_completion_signatures( - STDEXEC::get_completion_signatures<__sndr_t, - __result_env_t<__set_t, __child_t, _Env>...>(), - __eptr_completion_unless_t<__nothrow_t>())) + __cmplsigs::__append_range(__out, std::span{__cmpls}); + + if constexpr (!__nothrow_decay_copyable<_As...> + || !__nothrow_invocable<_Fun, __decay_t<_As>&...> + || (!__nothrow_connectable<__sndr2_t, __rcvr2_t<_Child, _Env>> || ...)) { - if constexpr (__sigs.template __contains()) - { - return __sigs; - } - else if constexpr (sizeof...(_Env) == 0) - { - return STDEXEC::__dependent_sender<__sndr_t>(); - } - else - { - using __env_t = __mfront<__result_env_t<__set_t, __child_t, _Env>...>; - using __rcvr_t = __receiver_archetype<__env_t>; - using __nothrow_t = __mbool<__nothrow_connectable<__sndr_t, __rcvr_t>>; - using __eptr_t = __eptr_completion_unless_t<__nothrow_t>; - - return STDEXEC::__concat_completion_signatures(__sigs, __eptr_t()); - } + __out.emplace_back(__signature<__eptr_sig_t>, __info.__domain, __info.__behavior); } + + return (__out); } - }; + } + }; - if constexpr (!__decay_copyable<_CvSndr>) + template <__completion_info _Info> + static constexpr auto __maybe_transform_cmplsig = + [](auto __transform, __cmpl_vec_t& __out) -> decltype(auto) + { + if constexpr (_Info.__disposition != __set_t::__disposition) { - return STDEXEC::__throw_compile_time_error<_SENDER_TYPE_IS_NOT_DECAY_COPYABLE_, - _WITH_PRETTY_SENDER_<_CvSndr>>(); + __out.push_back(_Info); + return (__out); } - else if constexpr (__same_as<_LetTag, let_value_t>) + else { - return STDEXEC::__transform_completion_signatures(__completions, __transform_fn); + using __sig_t = __mtypeof<_Info.__signature>; + return __transform(__signature<__sig_t>, _Info, __out); } - else if constexpr (__same_as<_LetTag, let_error_t>) + }; + + //! @tparam _Info A `__static_vector` of `__completion_info` objects representing + //! the completions of the predecessor sender. + template + static constexpr auto __get_cmpl_info_i = [](__indices<_Is...>) + { + return [] { - return STDEXEC::__transform_completion_signatures(__completions, {}, __transform_fn); - } - else + std::vector<__completion_info> __result; + // NB: this fold uses an overloaded comma operator that propagates __mexception + // objects when constexpr exceptions are not available. + return (__maybe_transform_cmplsig<_Info[_Is]>(_Transform, __result), ..., __result); + }; + }; + + template + static constexpr auto __get_cmpl_info = [] + { + constexpr auto __transform = __transform_cmplsig<_Fun, _Child, _Env...>; + constexpr auto __get_sig = &__completion_info::__signature; + constexpr auto __eptr_sig_id = __mtypeid<__eptr_sig_t>; + + STDEXEC_TRY_LET(constexpr auto __cmpls, STDEXEC::__get_cmpl_info<_Child, _Env...>()) { - return STDEXEC::__transform_completion_signatures(__completions, {}, {}, __transform_fn); + constexpr auto __idx = __make_indices<__cmpls.size()>(); + constexpr auto __get_cmpls2 = __get_cmpl_info_i<__cmpls, __transform>(__idx); + + STDEXEC_TRY_LET(constexpr auto __cmpls2, __cmplsigs::__completion_info_from(__get_cmpls2)) + { + if constexpr (std::ranges::find(__cmpls2, __eptr_sig_id, __get_sig) == __cmpls2.end() + && sizeof...(_Env) == 0) + return STDEXEC::__dependent_sender<_Child>(); + else + return __cmpls2; + } } + }; + + public: + static constexpr auto __get_attrs = + [](__ignore, __ignore, _Child const & __child) noexcept -> decltype(auto) + { + // TODO(ericniebler): this needs a proper implementation + return __fwd_env(STDEXEC::get_env(__child)); + }; + + template + static consteval auto __get_completion_signatures() + { + static_assert(__sender_for<_CvSender, _LetTag>); + constexpr auto __get_cmpl_info = + __impls::__get_cmpl_info<__fn_t<_CvSender>, __child_of<_CvSender>, _Env...>; + + if constexpr (!__decay_copyable<_CvSender>) + return STDEXEC::__throw_compile_time_error<_SENDER_TYPE_IS_NOT_DECAY_COPYABLE_, + _WITH_PRETTY_SENDER_<_CvSender>>(); + else + return __cmplsigs::__completion_sigs_from(__get_cmpl_info); } static constexpr auto __connect = diff --git a/include/stdexec/__detail/__meta.hpp b/include/stdexec/__detail/__meta.hpp index 9623bfcbb..1f4b595e8 100644 --- a/include/stdexec/__detail/__meta.hpp +++ b/include/stdexec/__detail/__meta.hpp @@ -51,12 +51,17 @@ namespace STDEXEC namespace __detail { // NB: This variable template is partially specialized for __type_index in __typeinfo.hpp: +#if STDEXEC_GCC() && STDEXEC_GCC_VERSION < 1300 template - extern __fn_ptr_t __mtypeof_v; + extern __mtype> __mtypeof_v; +#else + template + extern __mtype __mtypeof_v; +#endif } // namespace __detail template - using __mtypeof = decltype(__detail::__mtypeof_v<_Value>()); + using __mtypeof = decltype(__detail::__mtypeof_v<_Value>)::__t; template struct __mlist; @@ -203,7 +208,10 @@ namespace STDEXEC constexpr auto operator+() const -> _ERROR_; STDEXEC_ATTRIBUTE(host, device) - constexpr auto operator,(__ignore) const -> _ERROR_; + constexpr auto operator,(__ignore) const -> _ERROR_ + { + return *this; + } }; template @@ -869,19 +877,19 @@ namespace STDEXEC namespace __detail { template - extern __declfn_t<_Ty> __demangle_v; + extern __mtype<_Ty> __demangle_v; template - extern __declfn_t<_Ty &> __demangle_v<_Ty &>; + extern __mtype<_Ty &> __demangle_v<_Ty &>; template - extern __declfn_t<_Ty &&> __demangle_v<_Ty &&>; + extern __mtype<_Ty &&> __demangle_v<_Ty &&>; template - extern __declfn_t<_Ty const &> __demangle_v<_Ty const &>; + extern __mtype<_Ty const &> __demangle_v<_Ty const &>; template - using __demangle_t = decltype(__demangle_v<_Ty>()); + using __demangle_t = decltype(__demangle_v<_Ty>)::__t; } // namespace __detail // A utility for pretty-printing type names in diagnostics diff --git a/include/stdexec/__detail/__receivers.hpp b/include/stdexec/__detail/__receivers.hpp index d67dd8ff5..5650273b9 100644 --- a/include/stdexec/__detail/__receivers.hpp +++ b/include/stdexec/__detail/__receivers.hpp @@ -28,13 +28,6 @@ namespace STDEXEC { - enum class __disposition - { - __value, - __error, - __stopped - }; - namespace __detail { template <__disposition _Disposition> diff --git a/include/stdexec/__detail/__sequence.hpp b/include/stdexec/__detail/__sequence.hpp index ff9c37a5e..9ba8081a7 100644 --- a/include/stdexec/__detail/__sequence.hpp +++ b/include/stdexec/__detail/__sequence.hpp @@ -499,7 +499,7 @@ namespace STDEXEC namespace __detail { template - extern __declfn_t<__seq::__sndr<__demangle_t<_Senders>...>> + extern __mtype<__seq::__sndr<__demangle_t<_Senders>...>> __demangle_v<__seq::__sndr<_Senders...>>; } // namespace __detail } // namespace STDEXEC diff --git a/include/stdexec/__detail/__static_vector.hpp b/include/stdexec/__detail/__static_vector.hpp new file mode 100644 index 000000000..f32f45adf --- /dev/null +++ b/include/stdexec/__detail/__static_vector.hpp @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2026 NVIDIA Corporation + * + * Licensed under the Apache License Version 2.0 with LLVM Exceptions + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://llvm.org/LICENSE.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include "__execution_fwd.hpp" + +#include "__concepts.hpp" + +#include +#include +#include + +namespace STDEXEC +{ + template + struct __static_vector + { + using value_type = _Tp; + using iterator = value_type *; + using const_iterator = value_type const *; + + __static_vector() = default; + + constexpr __static_vector(std::initializer_list __init) + noexcept(__nothrow_copy_constructible) + { + auto const __end = std::copy_n(__init.begin(), (std::min) (__init.size(), _Size), __data_); + __size_ = __end - __data_; + } + + [[nodiscard]] + constexpr auto operator[](std::size_t __i) noexcept -> value_type & + { + return __data_[__i]; + } + + [[nodiscard]] + constexpr auto operator[](std::size_t __i) const noexcept -> value_type const & + { + return __data_[__i]; + } + + [[nodiscard]] + constexpr auto begin() noexcept -> iterator + { + return __data_; + } + + [[nodiscard]] + constexpr auto begin() const noexcept -> const_iterator + { + return __data_; + } + + [[nodiscard]] + constexpr auto end() noexcept -> iterator + { + return __data_ + __size_; + } + + [[nodiscard]] + constexpr auto end() const noexcept -> const_iterator + { + return __data_ + __size_; + } + + [[nodiscard]] + constexpr auto size() const noexcept -> std::size_t + { + return __size_; + } + + [[nodiscard]] + constexpr auto capacity() const noexcept -> std::size_t + { + return _Size; + } + + constexpr void resize(std::size_t __new_size) noexcept + { + __size_ = __new_size; + } + + constexpr auto erase(const_iterator __first, const_iterator __last) noexcept -> iterator + { + std::move(__last, end(), const_cast(__first)); + resize(size() - (__last - __first)); + return end(); + } + + std::size_t __size_ = 0; + value_type __data_[_Size]; + }; +} // namespace STDEXEC diff --git a/include/stdexec/__detail/__stopped_as_optional.hpp b/include/stdexec/__detail/__stopped_as_optional.hpp index 43e4f49b4..fd867b60a 100644 --- a/include/stdexec/__detail/__stopped_as_optional.hpp +++ b/include/stdexec/__detail/__stopped_as_optional.hpp @@ -66,8 +66,8 @@ namespace STDEXEC static constexpr auto __get_completion_signatures() { static_assert(__sender_for<_Self, stopped_as_optional_t>); - STDEXEC_COMPLSIGS_LET(__completions, - STDEXEC::get_completion_signatures<__child_of<_Self>, _Env...>()) + STDEXEC_TRY_LET(auto __completions, + STDEXEC::get_completion_signatures<__child_of<_Self>, _Env...>()) { using _Completions = decltype(__completions); if constexpr (__single_value_sender<__child_of<_Self>, _Env...>) diff --git a/include/stdexec/__detail/__transform_completion_signatures.hpp b/include/stdexec/__detail/__transform_completion_signatures.hpp index a61b441ff..0910e5272 100644 --- a/include/stdexec/__detail/__transform_completion_signatures.hpp +++ b/include/stdexec/__detail/__transform_completion_signatures.hpp @@ -575,9 +575,9 @@ namespace STDEXEC _StoppedFn __stopped_fn = {}, _ExtraSigs = {}) { - STDEXEC_COMPLSIGS_LET(__completions, _Completions{}) + STDEXEC_TRY_LET(auto __completions, _Completions{}) { - STDEXEC_COMPLSIGS_LET(__extra_sigs, _ExtraSigs{}) + STDEXEC_TRY_LET(auto __extra_sigs, _ExtraSigs{}) { __cmplsigs::__transform_one __tfx1{__value_fn, __error_fn, __stopped_fn}; return __concat_completion_signatures(__completions.__apply( diff --git a/include/stdexec/__detail/__typeinfo.hpp b/include/stdexec/__detail/__typeinfo.hpp index 9fa81172c..e7a78bd8f 100644 --- a/include/stdexec/__detail/__typeinfo.hpp +++ b/include/stdexec/__detail/__typeinfo.hpp @@ -97,8 +97,10 @@ namespace STDEXEC // __type_index struct __type_index { - constexpr __type_index(__type_info const &info) noexcept - : __info_(&info) + __type_index() = default; + + constexpr __type_index(__type_info const &__info) noexcept + : __info_(&__info) {} [[nodiscard]] @@ -108,15 +110,15 @@ namespace STDEXEC } [[nodiscard]] - constexpr bool operator==(__type_index const &other) const noexcept + constexpr bool operator==(__type_index const &__other) const noexcept { - return *__info_ == *other.__info_; + return *__info_ == *__other.__info_; } [[nodiscard]] - constexpr std::strong_ordering operator<=>(__type_index const &other) const noexcept + constexpr std::strong_ordering operator<=>(__type_index const &__other) const noexcept { - return *__info_ <=> *other.__info_; + return *__info_ <=> *__other.__info_; } #if !STDEXEC_NO_STDCPP_TYPEID() @@ -133,7 +135,7 @@ namespace STDEXEC } #endif - __type_info const *__info_; + __type_info const *__info_ = &__detail::__mtypeid_v; }; namespace __detail @@ -167,8 +169,7 @@ namespace STDEXEC // This specialization is what makes __mtypeof< Id > return the type associated with Id. template requires __same_as - extern __fn_t<__t()))>> - *__mtypeof_v<_Index>; + extern decltype(__typeid_lookup(__detail::__mtypeid_key<_Index>())) __mtypeof_v<_Index>; } // namespace __detail // For a given type, return a __type_index object diff --git a/include/stdexec/__detail/__utility.hpp b/include/stdexec/__detail/__utility.hpp index 9de462b55..71d642781 100644 --- a/include/stdexec/__detail/__utility.hpp +++ b/include/stdexec/__detail/__utility.hpp @@ -65,21 +65,18 @@ namespace STDEXEC struct __move_only { - __move_only() = default; - + __move_only() = default; __move_only(__move_only&&) noexcept = default; + __move_only(__move_only const &) = delete; auto operator=(__move_only&&) noexcept -> __move_only& = default; - - __move_only(__move_only const &) = delete; - auto operator=(__move_only const &) -> __move_only& = delete; + auto operator=(__move_only const &) -> __move_only& = delete; }; template using __call_result_t = decltype(__declval<_Fun>()(__declval<_As>()...)); template - using __call_result_or_t = - __mcall<__mtry_catch_q<__call_result_t, __mconst<_Default>>, _Fun, _As...>; + using __call_result_or_t = __minvoke_or_q<__call_result_t, _Default, _Fun, _As...>; // BUGBUG TODO file this bug with nvc++ #if STDEXEC_EDG() diff --git a/include/stdexec/execution.hpp b/include/stdexec/execution.hpp index 5f30676a1..9f5f6a4da 100644 --- a/include/stdexec/execution.hpp +++ b/include/stdexec/execution.hpp @@ -27,7 +27,6 @@ #include "__detail/__connect_awaitable.hpp" #include "__detail/__continues_on.hpp" #include "__detail/__counting_scopes.hpp" -#include "__detail/__cpo.hpp" #include "__detail/__debug.hpp" #include "__detail/__domain.hpp" #include "__detail/__env.hpp" diff --git a/include/stdexec/functional.hpp b/include/stdexec/functional.hpp index 09d0e8ed6..1c8b86e9d 100644 --- a/include/stdexec/functional.hpp +++ b/include/stdexec/functional.hpp @@ -267,12 +267,12 @@ namespace STDEXEC struct __construct_from { template - requires __std::constructible_from<_Ty, _As...> + requires __initializable_from<_Ty, _As...> STDEXEC_ATTRIBUTE(host, device, always_inline) - constexpr auto operator()(_As &&...__as) const noexcept( // - __nothrow_constructible_from<_Ty, _As...>) -> _Ty + constexpr auto + operator()(_As &&...__as) const noexcept(__nothrow_initializable_from<_Ty, _As...>) -> _Ty { - return _Ty(static_cast<_As &&>(__as)...); + return _Ty{static_cast<_As &&>(__as)...}; } }; @@ -363,8 +363,7 @@ namespace STDEXEC constexpr auto __bind_back(_Fn &&__fn, _BoundArgs... __bound_args) noexcept(__nothrow_move_constructible<_BoundArgs...> && __nothrow_decay_copyable<_Fn>) { - return __back_binder<__decay_t<_Fn>, _BoundArgs...>{static_cast<_Fn &&>(__fn), - static_cast<_BoundArgs &&>( - __bound_args)...}; + using __binder_t = __back_binder<__decay_t<_Fn>, _BoundArgs...>; + return __binder_t{static_cast<_Fn &&>(__fn), static_cast<_BoundArgs &&>(__bound_args)...}; }; } // namespace STDEXEC