diff --git a/libcudacxx/include/cuda/__memory_resource/resource.h b/libcudacxx/include/cuda/__memory_resource/resource.h index 2e9f72a63b8..d6085fa0d0b 100644 --- a/libcudacxx/include/cuda/__memory_resource/resource.h +++ b/libcudacxx/include/cuda/__memory_resource/resource.h @@ -36,14 +36,6 @@ _LIBCUDACXX_BEGIN_NAMESPACE_CUDA_MR -template -_LIBCUDACXX_CONCEPT_FRAGMENT( - __resource_, - requires(_Resource& __res, void* __ptr, size_t __bytes, size_t __alignment)( - requires(_CUDA_VSTD::same_as), - requires(_CUDA_VSTD::same_as), - requires(_CUDA_VSTD::equality_comparable<_Resource>))); - //! @brief The \c resource concept verifies that a type Resource satisfies the basic requirements of a memory //! resource //! @rst @@ -57,15 +49,11 @@ _LIBCUDACXX_CONCEPT_FRAGMENT( //! @endrst //! @tparam _Resource The type that should implement the resource concept template -_LIBCUDACXX_CONCEPT resource = _LIBCUDACXX_FRAGMENT(__resource_, _Resource); - -template -_LIBCUDACXX_CONCEPT_FRAGMENT( - __async_resource_, - requires(_Resource& __res, void* __ptr, size_t __bytes, size_t __alignment, ::cuda::stream_ref __stream)( - requires(resource<_Resource>), - requires(_CUDA_VSTD::same_as), - requires(_CUDA_VSTD::same_as))); +_LIBCUDACXX_CONCEPT resource = + _LIBCUDACXX_REQUIRES_EXPR((_Resource), _Resource& __res, void* __ptr, size_t __bytes, size_t __alignment)( + requires(_CUDA_VSTD::equality_comparable<_Resource>), + _Same_as(void*) __res.allocate(__bytes, __alignment), // + _Same_as(void) __res.deallocate(__ptr, __bytes, __alignment)); //! @brief The \c async_resource concept verifies that a type Resource satisfies the basic requirements of a //! memory resource and additionally supports stream ordered allocations @@ -83,7 +71,11 @@ _LIBCUDACXX_CONCEPT_FRAGMENT( //! @endrst //! @tparam _Resource The type that should implement the async resource concept template -_LIBCUDACXX_CONCEPT async_resource = _LIBCUDACXX_FRAGMENT(__async_resource_, _Resource); +_LIBCUDACXX_CONCEPT async_resource = _LIBCUDACXX_REQUIRES_EXPR( + (_Resource), _Resource& __res, void* __ptr, size_t __bytes, size_t __alignment, ::cuda::stream_ref __stream)( + requires(resource<_Resource>), + _Same_as(void*) __res.allocate_async(__bytes, __alignment, __stream), + _Same_as(void) __res.deallocate_async(__ptr, __bytes, __alignment, __stream)); //! @brief The \c resource_with concept verifies that a type Resource satisfies the `resource` concept and //! also satisfies all the provided Properties diff --git a/libcudacxx/include/cuda/std/__concepts/__concept_macros.h b/libcudacxx/include/cuda/std/__concepts/__concept_macros.h index b1eee235236..3fff35344ec 100644 --- a/libcudacxx/include/cuda/std/__concepts/__concept_macros.h +++ b/libcudacxx/include/cuda/std/__concepts/__concept_macros.h @@ -171,6 +171,7 @@ # define _LIBCUDACXX_PP_IIF_1(_TRUE, ...) _TRUE # define _LIBCUDACXX_PP_LPAREN ( +# define _LIBCUDACXX_PP_RPAREN ) # define _LIBCUDACXX_PP_NOT(_BIT) _LIBCUDACXX_PP_CAT_(_LIBCUDACXX_PP_NOT_, _BIT) # define _LIBCUDACXX_PP_NOT_0 1 @@ -220,11 +221,13 @@ # define _LIBCUDACXX_CONCEPT_FRAGMENT_REQS_SELECT_PROBE_requires _LIBCUDACXX_PP_PROBE_N(~, 1) # define _LIBCUDACXX_CONCEPT_FRAGMENT_REQS_SELECT_PROBE_noexcept _LIBCUDACXX_PP_PROBE_N(~, 2) # define _LIBCUDACXX_CONCEPT_FRAGMENT_REQS_SELECT_PROBE_typename _LIBCUDACXX_PP_PROBE_N(~, 3) +# define _LIBCUDACXX_CONCEPT_FRAGMENT_REQS_SELECT_PROBE__Same_as _LIBCUDACXX_PP_PROBE_N(~, 4) # define _LIBCUDACXX_CONCEPT_FRAGMENT_REQS_SELECT_0 _LIBCUDACXX_PP_EXPAND # define _LIBCUDACXX_CONCEPT_FRAGMENT_REQS_SELECT_1 _LIBCUDACXX_CONCEPT_FRAGMENT_REQS_REQUIRES_OR_NOEXCEPT # define _LIBCUDACXX_CONCEPT_FRAGMENT_REQS_SELECT_2 _LIBCUDACXX_CONCEPT_FRAGMENT_REQS_REQUIRES_OR_NOEXCEPT # define _LIBCUDACXX_CONCEPT_FRAGMENT_REQS_SELECT_3 _LIBCUDACXX_CONCEPT_FRAGMENT_REQS_REQUIRES_OR_NOEXCEPT +# define _LIBCUDACXX_CONCEPT_FRAGMENT_REQS_SELECT_4 _LIBCUDACXX_CONCEPT_FRAGMENT_REQS_SAME_AS # define _LIBCUDACXX_CONCEPT_FRAGMENT_REQS_REQUIRES_OR_NOEXCEPT(_REQ) \ _LIBCUDACXX_PP_CAT4(_LIBCUDACXX_CONCEPT_FRAGMENT_REQS_REQUIRES_, _REQ) # define _LIBCUDACXX_PP_EAT_TYPENAME_PROBE_typename _LIBCUDACXX_PP_PROBE(~) @@ -255,6 +258,15 @@ { \ __VA_ARGS__ \ } noexcept +# define _LIBCUDACXX_CONCEPT_FRAGMENT_REQS_SAME_AS(_REQ) \ + { \ + _LIBCUDACXX_PP_CAT4(_LIBCUDACXX_PP_EAT_SAME_AS_, _REQ) \ + } -> _LIBCUDACXX_CONCEPT_VSTD::same_as<_LIBCUDACXX_PP_EVAL( \ + _LIBCUDACXX_CONCEPT_FRAGMENT_REQS_SAME_AS_AUX, \ + _LIBCUDACXX_PP_CAT4(_LIBCUDACXX_CONCEPT_FRAGMENT_REQS_SAME_AS_, _REQ))> +# define _LIBCUDACXX_PP_EAT_SAME_AS__Same_as(...) +# define _LIBCUDACXX_CONCEPT_FRAGMENT_REQS_SAME_AS_AUX(_TYPE, ...) _LIBCUDACXX_PP_EXPAND _TYPE +# define _LIBCUDACXX_CONCEPT_FRAGMENT_REQS_SAME_AS__Same_as(...) (__VA_ARGS__), # define _LIBCUDACXX_FRAGMENT(_NAME, ...) _NAME<__VA_ARGS__> @@ -294,6 +306,10 @@ # else # define _LIBCUDACXX_CONCEPT_FRAGMENT_REQS_REQUIRES_noexcept(...) _Concept::_Requires # endif +# define _LIBCUDACXX_CONCEPT_FRAGMENT_REQS_SAME_AS(_REQ) \ + _Concept::_Requires<_CUDA_VSTD::same_as<_LIBCUDACXX_PP_CAT4( \ + _LIBCUDACXX_CONCEPT_FRAGMENT_REQS_SAME_AS_, _REQ) _LIBCUDACXX_PP_RPAREN>> +# define _LIBCUDACXX_CONCEPT_FRAGMENT_REQS_SAME_AS__Same_as(...) __VA_ARGS__, decltype _LIBCUDACXX_PP_LPAREN # define _LIBCUDACXX_FRAGMENT(_NAME, ...) \ (1u == sizeof(_NAME##_LIBCUDACXX_CONCEPT_FRAGMENT_(static_cast<_Concept::_Tag<__VA_ARGS__>*>(nullptr), nullptr))) @@ -323,6 +339,74 @@ # define _LIBCUDACXX_TRAILING_REQUIRES(...) ->_Concept::_Requires_t < __VA_ARGS__ _LIBCUDACXX_TRAILING_REQUIRES_AUX_ # endif +//////////////////////////////////////////////////////////////////////////////// +// _LIBCUDACXX_REQUIRES_EXPR +// Usage: +// template +// _LIBCUDACXX_CONCEPT equality_comparable = +// _LIBCUDACXX_REQUIRES_EXPR((T), T const& lhs, T const& rhs) ( +// lhs == rhs, +// lhs != rhs +// ); +// +// Can only be used as the last requirement in a concept definition. +# if defined(__cpp_concepts) && _CCCL_STD_VER >= 2020 +# define _LIBCUDACXX_REQUIRES_EXPR(_TY, ...) requires(__VA_ARGS__) _LIBCUDACXX_REQUIRES_EXPR_2 +# define _LIBCUDACXX_REQUIRES_EXPR_2(...) {_LIBCUDACXX_PP_FOR_EACH(_LIBCUDACXX_CONCEPT_FRAGMENT_REQS_M, __VA_ARGS__)} +# else +# define _LIBCUDACXX_REQUIRES_EXPR_TPARAM_PROBE_variadic _LIBCUDACXX_PP_PROBE(~) +# define _LIBCUDACXX_REQUIRES_EXPR_TPARAM_variadic + +# define _LIBCUDACXX_REQUIRES_EXPR_DEF_TPARAM(_TY) \ + , _LIBCUDACXX_PP_CAT(_LIBCUDACXX_REQUIRES_EXPR_DEF_TPARAM_, \ + _LIBCUDACXX_PP_EVAL(_LIBCUDACXX_PP_CHECK, \ + _LIBCUDACXX_PP_CAT(_LIBCUDACXX_REQUIRES_EXPR_TPARAM_PROBE_, _TY)))(_TY) +# define _LIBCUDACXX_REQUIRES_EXPR_DEF_TPARAM_0(_TY) class _TY +# define _LIBCUDACXX_REQUIRES_EXPR_DEF_TPARAM_1(_TY) \ + class... _LIBCUDACXX_PP_CAT(_LIBCUDACXX_REQUIRES_EXPR_TPARAM_, _TY) + +# define _LIBCUDACXX_REQUIRES_EXPR_EXPAND_TPARAM(_TY) \ + , _LIBCUDACXX_PP_CAT(_LIBCUDACXX_REQUIRES_EXPR_EXPAND_TPARAM_, \ + _LIBCUDACXX_PP_EVAL(_LIBCUDACXX_PP_CHECK, \ + _LIBCUDACXX_PP_CAT(_LIBCUDACXX_REQUIRES_EXPR_TPARAM_PROBE_, _TY)))(_TY) +# define _LIBCUDACXX_REQUIRES_EXPR_EXPAND_TPARAM_0(_TY) _TY +# define _LIBCUDACXX_REQUIRES_EXPR_EXPAND_TPARAM_1(_TY) _LIBCUDACXX_PP_CAT(_LIBCUDACXX_REQUIRES_EXPR_TPARAM_, _TY)... + +# define _LIBCUDACXX_REQUIRES_EXPR_TPARAMS(...) \ + _LIBCUDACXX_PP_FOR_EACH(_LIBCUDACXX_REQUIRES_EXPR_DEF_TPARAM, __VA_ARGS__) + +# define _LIBCUDACXX_REQUIRES_EXPR_EXPAND_TPARAMS(...) \ + _LIBCUDACXX_PP_FOR_EACH(_LIBCUDACXX_REQUIRES_EXPR_EXPAND_TPARAM, __VA_ARGS__) + +# define _LIBCUDACXX_REQUIRES_EXPR(_TY, ...) \ + _Concept::_Requires_expr_impl:: \ + _Is_satisfied(static_cast<_Concept::_Tag*>(nullptr), \ + static_cast(nullptr)); \ + struct _LIBCUDACXX_PP_CAT(_Libcudacxx_requires_expr_detail_, __LINE__) \ + { \ + using _Self_t = _LIBCUDACXX_PP_CAT(_Libcudacxx_requires_expr_detail_, __LINE__); \ + template \ + _LIBCUDACXX_HIDE_FROM_ABI static auto _Well_formed(__VA_ARGS__) _LIBCUDACXX_REQUIRES_EXPR_2 + +# define _LIBCUDACXX_REQUIRES_EXPR_2(...) \ + ->decltype(_LIBCUDACXX_PP_FOR_EACH(_LIBCUDACXX_CONCEPT_FRAGMENT_REQS_M, __VA_ARGS__) void()) {} \ + template (&_Self_t::_Well_formed))> \ + _LIBCUDACXX_HIDE_FROM_ABI static constexpr bool _Is_satisfied(_Concept::_Tag*, Sig*) \ + { \ + return true; \ + } \ + _LIBCUDACXX_HIDE_FROM_ABI static constexpr bool _Is_satisfied(void*, ...) \ + { \ + return false; \ + } \ + } +# endif + +// So that we can refer to the ::cuda::std namespace below +_LIBCUDACXX_BEGIN_NAMESPACE_STD +_LIBCUDACXX_END_NAMESPACE_STD + namespace _Concept { template @@ -344,6 +428,7 @@ using _Requires_t = typename _Select<_Bp>::template type<_Tp>; template struct _Tag; + template _LIBCUDACXX_HIDE_FROM_ABI constexpr bool _Is_true() { @@ -358,6 +443,28 @@ _LIBCUDACXX_HIDE_FROM_ABI _Concept::_Enable_if_t<_Bp> _Requires() template = 0> _CCCL_INLINE_VAR constexpr int _Requires = 0; # endif + +template +_LIBCUDACXX_HIDE_FROM_ABI auto _Make_dependent(_Tp*, _Tag<_Args...>*) -> _Tp; + +template +using _Requires_expr_impl = // + decltype(_Concept::_Make_dependent(static_cast<_Impl*>(nullptr), static_cast<_Tag*>(nullptr))); + +// We put an alias for _CUDA_VSTD here because of a bug in nvcc <12.2 +// where a requirement such as: +// +// { expression } -> ::concept +// +// where ::concept is a fully qualified name, would not compile. The +// _CUDA_VSTD macro is fully qualified. +namespace _Vstd = _CUDA_VSTD; // NOLINT(misc-unused-alias-decls) + +# if defined(_CCCL_CUDACC_BELOW_12_2) +# define _LIBCUDACXX_CONCEPT_VSTD _Concept::_Vstd // must not be fully qualified +# else +# define _LIBCUDACXX_CONCEPT_VSTD _CUDA_VSTD +# endif } // namespace _Concept #endif // _CCCL_STD_VER > 2011