Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add _LIBCUDACXX_REQUIRES_EXPR to the concepts emulation macros #2564

Merged
merged 9 commits into from
Oct 16, 2024
28 changes: 10 additions & 18 deletions libcudacxx/include/cuda/__memory_resource/resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,6 @@

_LIBCUDACXX_BEGIN_NAMESPACE_CUDA_MR

template <class _Resource>
_LIBCUDACXX_CONCEPT_FRAGMENT(
__resource_,
requires(_Resource& __res, void* __ptr, size_t __bytes, size_t __alignment)(
requires(_CUDA_VSTD::same_as<void*, decltype(__res.allocate(__bytes, __alignment))>),
requires(_CUDA_VSTD::same_as<void, decltype(__res.deallocate(__ptr, __bytes, __alignment))>),
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
Expand All @@ -57,15 +49,11 @@ _LIBCUDACXX_CONCEPT_FRAGMENT(
//! @endrst
//! @tparam _Resource The type that should implement the resource concept
template <class _Resource>
_LIBCUDACXX_CONCEPT resource = _LIBCUDACXX_FRAGMENT(__resource_, _Resource);

template <class _Resource>
_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<void*, decltype(__res.allocate_async(__bytes, __alignment, __stream))>),
requires(_CUDA_VSTD::same_as<void, decltype(__res.deallocate_async(__ptr, __bytes, __alignment, __stream))>)));
_LIBCUDACXX_CONCEPT resource =
_CUDA_VSTD::equality_comparable<_Resource>
&& _LIBCUDACXX_REQUIRES_EXPR((_Resource), _Resource& __res, void* __ptr, size_t __bytes, size_t __alignment)(
_Same_as(void*) __res.allocate(__bytes, __alignment), //
_Same_as(void) __res.deallocate(__ptr, __bytes, __alignment));
miscco marked this conversation as resolved.
Show resolved Hide resolved

//! @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
Expand All @@ -83,7 +71,11 @@ _LIBCUDACXX_CONCEPT_FRAGMENT(
//! @endrst
//! @tparam _Resource The type that should implement the async resource concept
template <class _Resource>
_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
Expand Down
107 changes: 107 additions & 0 deletions libcudacxx/include/cuda/std/__concepts/__concept_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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(~)
Expand Down Expand Up @@ -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__>

Expand Down Expand Up @@ -294,6 +306,10 @@
# else
# define _LIBCUDACXX_CONCEPT_FRAGMENT_REQS_REQUIRES_noexcept(...) _Concept::_Requires<noexcept(__VA_ARGS__)>
# 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)))
Expand Down Expand Up @@ -323,6 +339,74 @@
# define _LIBCUDACXX_TRAILING_REQUIRES(...) ->_Concept::_Requires_t < __VA_ARGS__ _LIBCUDACXX_TRAILING_REQUIRES_AUX_
# endif

////////////////////////////////////////////////////////////////////////////////
// _LIBCUDACXX_REQUIRES_EXPR
// Usage:
// template <typename T>
// _LIBCUDACXX_CONCEPT equality_comparable =
// _LIBCUDACXX_REQUIRES_EXPR((T), T const& lhs, T const& rhs) (
miscco marked this conversation as resolved.
Show resolved Hide resolved
// 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<struct _LIBCUDACXX_PP_CAT(_Libcudacxx_requires_expr_detail_, __LINE__) \
_LIBCUDACXX_REQUIRES_EXPR_EXPAND_TPARAMS _TY>:: \
_Is_satisfied(static_cast<_Concept::_Tag<void _LIBCUDACXX_REQUIRES_EXPR_EXPAND_TPARAMS _TY>*>(nullptr), \
static_cast<void (*)(__VA_ARGS__)>(nullptr)); \
struct _LIBCUDACXX_PP_CAT(_Libcudacxx_requires_expr_detail_, __LINE__) \
{ \
using _Self_t = _LIBCUDACXX_PP_CAT(_Libcudacxx_requires_expr_detail_, __LINE__); \
template <class _LIBCUDACXX_REQUIRES_EXPR_TPARAMS _TY> \
_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 <class... Args, class Sig, class = decltype(static_cast<Sig*>(&_Self_t::_Well_formed<Args...>))> \
_LIBCUDACXX_HIDE_FROM_ABI static constexpr bool _Is_satisfied(_Concept::_Tag<Args...>*, 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 <bool>
Expand All @@ -344,6 +428,7 @@ using _Requires_t = typename _Select<_Bp>::template type<_Tp>;

template <typename...>
struct _Tag;

template <class>
_LIBCUDACXX_HIDE_FROM_ABI constexpr bool _Is_true()
{
Expand All @@ -358,6 +443,28 @@ _LIBCUDACXX_HIDE_FROM_ABI _Concept::_Enable_if_t<_Bp> _Requires()
template <bool _Bp, _Concept::_Enable_if_t<_Bp, int> = 0>
_LIBCUDACXX_INLINE_VAR constexpr int _Requires = 0;
# endif

template <class _Tp, class... _Args>
_LIBCUDACXX_HIDE_FROM_ABI auto _Make_dependent(_Tp*, _Tag<_Args...>*) -> _Tp;

template <class _Impl, class... _Args>
using _Requires_expr_impl = //
decltype(_Concept::_Make_dependent(static_cast<_Impl*>(nullptr), static_cast<_Tag<void, _Args...>*>(nullptr)));

// We put an alias for _CUDA_VSTD here because of a bug in nvcc <12.2
// where a requirement such as:
//
// { expression } -> ::concept<type>
//
// 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
Expand Down
Loading