@@ -246,13 +246,13 @@ namespace stdexec {
246246
247247 struct __is_scheduler_affine_t {
248248 template <class _Env >
249- constexpr auto operator ()(const _Env&) const noexcept {
250- if constexpr (tag_invocable< __is_scheduler_affine_t , const _Env&> ) {
251- using _Result = __decay_t < tag_invoke_result_t < __is_scheduler_affine_t , const _Env&>> ;
252- static_assert (__same_as< decltype (__v<_Result>), const bool >);
253- return _Result ( );
249+ constexpr auto operator ()(const _Env& __env ) const noexcept {
250+ if constexpr (requires { _Env::query (* this ); } ) {
251+ return _Env::query (* this ) ;
252+ } else if constexpr ( requires { __env. query (* this ); }) {
253+ return __env. query (* this );
254254 } else {
255- return std::false_type () ;
255+ return false ;
256256 }
257257 }
258258
@@ -410,6 +410,18 @@ namespace stdexec {
410410 STDEXEC_HOST_DEVICE_DEDUCTION_GUIDE
411411 prop (_Query, _Value) -> prop<_Query, std::unwrap_reference_t <_Value>>;
412412
413+ template <class _Query , auto _Value>
414+ struct cprop {
415+ using __t = cprop;
416+ using __id = cprop;
417+
418+ STDEXEC_ATTRIBUTE (nodiscard)
419+
420+ static constexpr auto query (_Query) noexcept {
421+ return _Value;
422+ }
423+ };
424+
413425 // utility for joining multiple environments
414426 template <class ... _Envs>
415427 struct env {
@@ -432,6 +444,23 @@ namespace stdexec {
432444 template <class _Query , class ... _Args>
433445 using __1st_env_t = decltype (env::__get_1st<_Query, _Args...>(__declval<const env&>()));
434446
447+ // NOT TO SPEC: a static query memfn for those envs that have a static query memfn.
448+ // This is useful for constexpr evaluation of queries.
449+ template <class _Query , class ... _Args>
450+ requires (__queryable<_Envs, _Query, _Args...> || ...)
451+ STDEXEC_ATTRIBUTE (always_inline)
452+ static constexpr auto query (_Query __q, _Args&&... __args)
453+ noexcept (__nothrow_queryable<__1st_env_t <_Query, _Args...>, _Query, _Args...>)
454+ -> decltype(auto )
455+ requires requires {
456+ std::remove_reference_t <__1st_env_t <_Query, _Args...>>::query (
457+ __q, static_cast <_Args &&>(__args)...);
458+ }
459+ {
460+ return std::remove_reference_t <__1st_env_t <_Query, _Args...>>::query (
461+ __q, static_cast <_Args&&>(__args)...);
462+ }
463+
435464 template <class _Query , class ... _Args>
436465 requires (__queryable<_Envs, _Query, _Args...> || ...)
437466 STDEXEC_ATTRIBUTE (always_inline)
@@ -467,6 +496,24 @@ namespace stdexec {
467496 template <class _Query , class ... _Args>
468497 using __1st_env_t = decltype (env::__get_1st<_Query, _Args...>(__declval<const env&>()));
469498
499+ // NOT TO SPEC: a static query memfn for those envs that have a static query memfn.
500+ // This is useful for constexpr evaluation of queries.
501+ template <class _Query , class ... _Args>
502+ requires __queryable<_Env0, _Query, _Args...>
503+ || __queryable<_Env1, _Query, _Args...>
504+ STDEXEC_ATTRIBUTE (always_inline)
505+ static constexpr auto query (_Query __q, _Args&&... __args)
506+ noexcept (__nothrow_queryable<__1st_env_t <_Query, _Args...>, _Query, _Args...>)
507+ -> decltype(auto )
508+ requires requires {
509+ std::remove_reference_t <__1st_env_t <_Query, _Args...>>::query (
510+ __q, static_cast <_Args &&>(__args)...);
511+ }
512+ {
513+ return std::remove_reference_t <__1st_env_t <_Query, _Args...>>::query (
514+ __q, static_cast <_Args&&>(__args)...);
515+ }
516+
470517 template <class _Query , class ... _Args>
471518 requires __queryable<_Env0, _Query, _Args...> || __queryable<_Env1, _Query, _Args...>
472519 STDEXEC_ATTRIBUTE (always_inline)
@@ -765,7 +812,7 @@ namespace stdexec {
765812
766813 template <class _Sender >
767814 concept __is_scheduler_affine = requires {
768- requires __v< __call_result_t < __is_scheduler_affine_t , env_of_t <_Sender>>> ;
815+ requires env_of_t <_Sender>:: query ( __is_scheduler_affine_t {}) ;
769816 };
770817} // namespace stdexec
771818
0 commit comments