@@ -342,35 +342,43 @@ namespace stdexec {
342342 // ///////////////////////////////////////////////////////////////////////////
343343 namespace __get_env {
344344 template <class _EnvProvider >
345- concept __has_get_env = requires (const _EnvProvider& __env_provider) {
346- __env_provider.get_env ();
347- };
345+ using __get_env_member_t = decltype (__declval<_EnvProvider>().get_env());
346+
347+ template <class _EnvProvider >
348+ concept __has_get_env = __mvalid<__get_env_member_t , _EnvProvider>;
348349
349350 // For getting an execution environment from a receiver or the attributes from a sender.
350351 struct get_env_t {
352+ private:
351353 template <class _EnvProvider >
352- requires __has_get_env<_EnvProvider>
353- STDEXEC_ATTRIBUTE (nodiscard, always_inline, host, device)
354- constexpr auto operator ()(const _EnvProvider& __env_provider) const noexcept
355- -> decltype(__env_provider.get_env()) {
356- static_assert (queryable<decltype (__env_provider.get_env ())>);
357- static_assert (noexcept (__env_provider.get_env ()), " get_env() members must be noexcept" );
358- return __env_provider.get_env ();
359- }
360-
361- template <class _EnvProvider >
362- requires (!__has_get_env<_EnvProvider>) && tag_invocable<get_env_t , const _EnvProvider&>
363- STDEXEC_ATTRIBUTE (nodiscard, always_inline, host, device)
364- constexpr auto operator ()(const _EnvProvider& __env_provider) const noexcept
365- -> tag_invoke_result_t<get_env_t, const _EnvProvider&> {
366- static_assert (queryable<tag_invoke_result_t <get_env_t , const _EnvProvider&>>);
367- static_assert (nothrow_tag_invocable<get_env_t , const _EnvProvider&>);
368- return tag_invoke (*this , __env_provider);
354+ static constexpr auto __get_declfn () noexcept {
355+ constexpr __declfn_t <_EnvProvider> __env_provider{};
356+ if constexpr (__has_get_env<_EnvProvider>) {
357+ using __result_t = __get_env_member_t <_EnvProvider>;
358+ static_assert (noexcept (__env_provider ().get_env ()), " get_env() members must be noexcept" );
359+ return __declfn<__result_t >();
360+ } else if constexpr (tag_invocable<get_env_t , const _EnvProvider&>) {
361+ using __result_t = tag_invoke_result_t <get_env_t , const _EnvProvider&>;
362+ constexpr bool __is_nothrow = nothrow_tag_invocable<get_env_t , const _EnvProvider&>;
363+ static_assert (__is_nothrow, " get_env tag_invoke overloads must be noexcept" );
364+ return __declfn<__result_t >();
365+ } else {
366+ return __declfn<env<>>();
367+ }
369368 }
370369
370+ public:
371+ template <class _EnvProvider , auto _DeclFn = __get_declfn<_EnvProvider>()>
371372 STDEXEC_ATTRIBUTE (nodiscard, always_inline, host, device)
372- constexpr auto operator ()(__ignore) const noexcept -> env<> {
373- return {};
373+ constexpr auto
374+ operator ()(const _EnvProvider& __env_provider) const noexcept -> decltype (_DeclFn()) {
375+ if constexpr (__has_get_env<_EnvProvider>) {
376+ return __env_provider.get_env ();
377+ } else if constexpr (tag_invocable<get_env_t , const _EnvProvider&>) {
378+ return tag_invoke (*this , __env_provider);
379+ } else {
380+ return env<>{};
381+ }
374382 }
375383 };
376384 } // namespace __get_env
0 commit comments