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

minor consistency improvements in concepts macros #2928

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
155 changes: 75 additions & 80 deletions libcudacxx/include/cuda/std/__concepts/concept_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//

#ifndef _CUDA___CONCEPTS
#define _CUDA___CONCEPTS
#ifndef _CUDA___CONCEPTS_CONCEPT_MACROS
#define _CUDA___CONCEPTS_CONCEPT_MACROS

#include <cuda/std/detail/__config>

Expand All @@ -24,6 +24,10 @@
# pragma system_header
#endif // no system header

// So that we can refer to the ::cuda::std namespace below
_LIBCUDACXX_BEGIN_NAMESPACE_STD
_LIBCUDACXX_END_NAMESPACE_STD

////////////////////////////////////////////////////////////////////////////////
// _CCCL_TEMPLATE
// Usage:
Expand All @@ -50,56 +54,25 @@ using __cccl_enable_if_t = typename __cccl_select<_Bp>::template type<_Tp>;
template <class _Tp, bool _Bp>
using __cccl_requires_t = typename __cccl_select<_Bp>::template type<_Tp>;

#if (defined(__cpp_concepts) && _CCCL_STD_VER >= 2020)
# define _CCCL_TEMPLATE(...) template <__VA_ARGS__>
# define _CCCL_REQUIRES(...) requires __VA_ARGS__
# define _CCCL_AND &&
# define _CCCL_TRAILING_REQUIRES_AUX_(...) requires __VA_ARGS__
# define _CCCL_TRAILING_REQUIRES(...) ->__VA_ARGS__ _CCCL_TRAILING_REQUIRES_AUX_
#else // ^^^ __cpp_concepts ^^^ / vvv !__cpp_concepts vvv
# define _CCCL_TEMPLATE(...) template <__VA_ARGS__
# define _CCCL_REQUIRES(...) , bool _CCCL_true_ = true, __cccl_enable_if_t < __VA_ARGS__ && _CCCL_true_, int > = 0 >
# define _CCCL_AND &&_CCCL_true_, int > = 0, __cccl_enable_if_t <
# define _CCCL_TRAILING_REQUIRES_AUX_(...) , __VA_ARGS__ >
# define _CCCL_TRAILING_REQUIRES(...) ->__cccl_requires_t < __VA_ARGS__ _CCCL_TRAILING_REQUIRES_AUX_
#endif // !__cpp_concepts
template <class...>
struct __cccl_tag;

#if _CCCL_STD_VER >= 2014
template <bool _Bp, class _Int = __cccl_enable_if_t<_Bp, int>>
using __cccl_requires = _Int;

namespace __cccl_concept
{
template <class _Tp, class... _Args>
_LIBCUDACXX_HIDE_FROM_ABI auto __cccl_make_dependent(_Tp*, __cccl_tag<_Args...>*) -> _Tp;

template <typename...>
struct _Tag;
template <class _Impl, class... _Args>
using __requires_expr_impl =
decltype(__cccl_make_dependent(static_cast<_Impl*>(nullptr), static_cast<__cccl_tag<void, _Args...>*>(nullptr)));

template <class>
_LIBCUDACXX_HIDE_FROM_ABI constexpr bool __is_true()
_LIBCUDACXX_HIDE_FROM_ABI constexpr bool __cccl_is_true()
{
return true;
}

# if _CCCL_COMPILER(CLANG) || defined(_CCCL_COMPILER_MSVC)
template <bool _Bp>
_LIBCUDACXX_HIDE_FROM_ABI __cccl_enable_if_t<_Bp> __cccl_requires()
{}
# else // ^^^ _CCCL_COMPILER(CLANG) || defined(_CCCL_COMPILER_MSVC) ^^^ / vvv other compilers vvv
template <bool _Bp, __cccl_enable_if_t<_Bp, int> = 0>
_CCCL_INLINE_VAR constexpr int __cccl_requires = 0;
# endif // !_CCCL_COMPILER(CLANG) && !defined(_CCCL_COMPILER_MSVC)

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

template <class _Impl, class... _Args>
using __requires_expr_impl =
decltype(__cccl_make_dependent(static_cast<_Impl*>(nullptr), static_cast<_Tag<void, _Args...>*>(nullptr)));

} // namespace __cccl_concept

// So that we can refer to the ::cuda::std namespace below
_LIBCUDACXX_BEGIN_NAMESPACE_STD
_LIBCUDACXX_END_NAMESPACE_STD

// We put an alias for _CUDA_VSTD here because of a bug in nvcc <12.2
// where a requirement such as:
//
Expand All @@ -109,11 +82,29 @@ _LIBCUDACXX_END_NAMESPACE_STD
// _CUDA_VSTD macro is fully qualified.
namespace __unqualified_cuda_std = _CUDA_VSTD; // NOLINT(misc-unused-alias-decls)

# if _CCCL_CUDACC_BELOW(12, 2)
# define _CCCL_CONCEPT_VSTD __unqualified_cuda_std // must not be fully qualified
# else
# define _CCCL_CONCEPT_VSTD _CUDA_VSTD
# endif
#if _CCCL_CUDACC_BELOW(12, 2)
# define _CCCL_CONCEPT_VSTD __unqualified_cuda_std // must not be fully qualified
#else
# define _CCCL_CONCEPT_VSTD _CUDA_VSTD
#endif

// clang-format off
ericniebler marked this conversation as resolved.
Show resolved Hide resolved
#if (defined(__cpp_concepts) && _CCCL_STD_VER >= 2020) || defined(_CCCL_DOXYGEN_INVOKED)
# define _CCCL_TEMPLATE(...) template <__VA_ARGS__>
# define _CCCL_REQUIRES(...) requires __VA_ARGS__
# define _CCCL_AND &&
# define _CCCL_TRAILING_REQUIRES_AUX_(...) requires __VA_ARGS__
# define _CCCL_TRAILING_REQUIRES(...) -> __VA_ARGS__ _CCCL_TRAILING_REQUIRES_AUX_
#else // ^^^ __cpp_concepts ^^^ / vvv !__cpp_concepts vvv
# define _CCCL_TEMPLATE(...) template <__VA_ARGS__
# define _CCCL_REQUIRES(...) , bool __cccl_true_ = true, __cccl_enable_if_t<__VA_ARGS__ && __cccl_true_, int> = 0>
# define _CCCL_AND && __cccl_true_, int> = 0, __cccl_enable_if_t<
# define _CCCL_TRAILING_REQUIRES_AUX_(...) , __VA_ARGS__>
# define _CCCL_TRAILING_REQUIRES(...) -> __cccl_requires_t<__VA_ARGS__ _CCCL_TRAILING_REQUIRES_AUX_
#endif // !__cpp_concepts
// clang-format on

#if _CCCL_STD_VER >= 2014

# define _CCCL_CONCEPT_FRAGMENT_REQS_M0(_REQ) _CCCL_CONCEPT_FRAGMENT_REQS_SELECT_(_REQ)(_REQ)
# define _CCCL_CONCEPT_FRAGMENT_REQS_M1(_REQ) _CCCL_PP_EXPAND _REQ
Expand Down Expand Up @@ -178,13 +169,13 @@ namespace __unqualified_cuda_std = _CUDA_VSTD; // NOLINT(misc-unused-alias-decls
# define _CCCL_CONCEPT_FRAGMENT(_NAME, ...) \
_LIBCUDACXX_HIDE_FROM_ABI auto _NAME##_CCCL_CONCEPT_FRAGMENT_impl_ _CCCL_CONCEPT_FRAGMENT_REQS_##__VA_ARGS__ > { \
} \
template <typename... _As> \
template <class... _As> \
_LIBCUDACXX_HIDE_FROM_ABI char _NAME##_CCCL_CONCEPT_FRAGMENT_( \
__cccl_concept::_Tag<_As...>*, decltype(&_NAME##_CCCL_CONCEPT_FRAGMENT_impl_<_As...>)); \
::__cccl_tag<_As...>*, decltype(&_NAME##_CCCL_CONCEPT_FRAGMENT_impl_<_As...>)); \
_LIBCUDACXX_HIDE_FROM_ABI char(&_NAME##_CCCL_CONCEPT_FRAGMENT_(...))[2] /**/
# if defined(_MSC_VER) && !defined(__clang__)
# define _CCCL_CONCEPT_FRAGMENT_TRUE(...) \
__cccl_concept::__is_true<decltype(_CCCL_PP_FOR_EACH(_CCCL_CONCEPT_FRAGMENT_REQS_M, __VA_ARGS__) void())>()
::__cccl_is_true<decltype(_CCCL_PP_FOR_EACH(_CCCL_CONCEPT_FRAGMENT_REQS_M, __VA_ARGS__) void())>()
# else
# define _CCCL_CONCEPT_FRAGMENT_TRUE(...) \
!(decltype(_CCCL_PP_FOR_EACH(_CCCL_CONCEPT_FRAGMENT_REQS_M, __VA_ARGS__) void(), false){})
Expand All @@ -194,23 +185,25 @@ namespace __unqualified_cuda_std = _CUDA_VSTD; // NOLINT(misc-unused-alias-decls
# define _CCCL_CONCEPT_FRAGMENT_REQS_M(_REQ) \
_CCCL_PP_CAT2(_CCCL_CONCEPT_FRAGMENT_REQS_M, _CCCL_PP_IS_PAREN(_REQ)) \
(_REQ),
# define _CCCL_CONCEPT_FRAGMENT_REQS_REQUIRES_requires(...) __cccl_concept::__cccl_requires<__VA_ARGS__>
# define _CCCL_CONCEPT_FRAGMENT_REQS_REQUIRES_typename(...) static_cast<__cccl_concept::_Tag<__VA_ARGS__>*>(nullptr)
# define _CCCL_CONCEPT_FRAGMENT_REQS_REQUIRES_requires(...) \
::__cccl_requires<__VA_ARGS__> {}
# define _CCCL_CONCEPT_FRAGMENT_REQS_REQUIRES_typename(...) static_cast<::__cccl_tag<__VA_ARGS__>*>(nullptr)
# if _CCCL_COMPILER(GCC, <, 14)
// GCC < 14 can't mangle noexcept expressions, so just check that the
// expression is well-formed.
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70790
# define _CCCL_CONCEPT_FRAGMENT_REQS_REQUIRES_noexcept(...) __VA_ARGS__
# else
# define _CCCL_CONCEPT_FRAGMENT_REQS_REQUIRES_noexcept(...) __cccl_concept::__cccl_requires<noexcept(__VA_ARGS__)>
# define _CCCL_CONCEPT_FRAGMENT_REQS_REQUIRES_noexcept(...) \
::__cccl_requires<noexcept(__VA_ARGS__)> {}
# endif
# define _CCCL_CONCEPT_FRAGMENT_REQS_SAME_AS(_REQ) \
__cccl_concept::__cccl_requires< \
_CUDA_VSTD::same_as<_CCCL_PP_CAT4(_CCCL_CONCEPT_FRAGMENT_REQS_SAME_AS_, _REQ) _CCCL_PP_RPAREN>>
# define _CCCL_CONCEPT_FRAGMENT_REQS_SAME_AS(_REQ) \
::__cccl_requires<_CUDA_VSTD::same_as<_CCCL_PP_CAT4(_CCCL_CONCEPT_FRAGMENT_REQS_SAME_AS_, _REQ) _CCCL_PP_RPAREN>> \
{}
# define _CCCL_CONCEPT_FRAGMENT_REQS_SAME_AS__Same_as(...) __VA_ARGS__, decltype _CCCL_PP_LPAREN

# define _CCCL_FRAGMENT(_NAME, ...) \
(1u == sizeof(_NAME##_CCCL_CONCEPT_FRAGMENT_(static_cast<__cccl_concept::_Tag<__VA_ARGS__>*>(nullptr), nullptr)))
(1u == sizeof(_NAME##_CCCL_CONCEPT_FRAGMENT_(static_cast<::__cccl_tag<__VA_ARGS__>*>(nullptr), nullptr)))

# endif

Expand All @@ -225,9 +218,9 @@ namespace __unqualified_cuda_std = _CUDA_VSTD; // NOLINT(misc-unused-alias-decls
// );
//
// Can only be used as the last requirement in a concept definition.
# if defined(__cpp_concepts) && _CCCL_STD_VER >= 2020
# define _CCCL_REQUIRES_EXPR(_TY, ...) requires(__VA_ARGS__) _CCCL_REQUIRES_EXPR_2
# define _CCCL_REQUIRES_EXPR_2(...) {_CCCL_PP_FOR_EACH(_CCCL_CONCEPT_FRAGMENT_REQS_M, __VA_ARGS__)}
# if defined(__cpp_concepts) && _CCCL_STD_VER >= 2020 || defined(_CCCL_DOXYGEN_INVOKED)
# define _CCCL_REQUIRES_EXPR(_TY, ...) requires(__VA_ARGS__) _CCCL_REQUIRES_EXPR_IMPL
# define _CCCL_REQUIRES_EXPR_IMPL(...) {_CCCL_PP_FOR_EACH(_CCCL_CONCEPT_FRAGMENT_REQS_M, __VA_ARGS__)}
# else
# define _CCCL_REQUIRES_EXPR_TPARAM_PROBE_variadic _CCCL_PP_PROBE(~)
# define _CCCL_REQUIRES_EXPR_TPARAM_variadic
Expand All @@ -249,30 +242,32 @@ namespace __unqualified_cuda_std = _CUDA_VSTD; // NOLINT(misc-unused-alias-decls
# define _CCCL_REQUIRES_EXPR_EXPAND_TPARAMS(...) _CCCL_PP_FOR_EACH(_CCCL_REQUIRES_EXPR_EXPAND_TPARAM, __VA_ARGS__)

# define _CCCL_REQUIRES_EXPR(_TY, ...) \
__cccl_concept::__requires_expr_impl<struct _CCCL_PP_CAT( \
__cccl_requires_expr_detail_, __LINE__) _CCCL_REQUIRES_EXPR_EXPAND_TPARAMS _TY>:: \
__cccl_is_satisfied(static_cast<__cccl_concept::_Tag<void _CCCL_REQUIRES_EXPR_EXPAND_TPARAMS _TY>*>(nullptr), \
static_cast<void (*)(__VA_ARGS__)>(nullptr)); \
::__requires_expr_impl< \
struct _CCCL_PP_CAT(__cccl_requires_expr_detail_, __LINE__) _CCCL_REQUIRES_EXPR_EXPAND_TPARAMS \
_TY>::__cccl_is_satisfied(static_cast<::__cccl_tag<void _CCCL_REQUIRES_EXPR_EXPAND_TPARAMS _TY>*>(nullptr), \
static_cast<void (*)(__VA_ARGS__)>(nullptr)); \
struct _CCCL_PP_CAT(__cccl_requires_expr_detail_, __LINE__) \
{ \
using _Self_t = _CCCL_PP_CAT(__cccl_requires_expr_detail_, __LINE__); \
using __cccl_self_t = _CCCL_PP_CAT(__cccl_requires_expr_detail_, __LINE__); \
template <class _CCCL_REQUIRES_EXPR_TPARAMS _TY> \
_LIBCUDACXX_HIDE_FROM_ABI static auto _Well_formed(__VA_ARGS__) _CCCL_REQUIRES_EXPR_2

# define _CCCL_REQUIRES_EXPR_2(...) \
->decltype(_CCCL_PP_FOR_EACH(_CCCL_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 __cccl_is_satisfied(__cccl_concept::_Tag<Args...>*, Sig*) \
{ \
return true; \
} \
_LIBCUDACXX_HIDE_FROM_ABI static constexpr bool __cccl_is_satisfied(void*, ...) \
{ \
return false; \
} \
_LIBCUDACXX_HIDE_FROM_ABI static auto __cccl_well_formed(__VA_ARGS__) _CCCL_REQUIRES_EXPR_IMPL

# define _CCCL_REQUIRES_EXPR_IMPL(...) \
->decltype(_CCCL_PP_FOR_EACH(_CCCL_CONCEPT_FRAGMENT_REQS_M, __VA_ARGS__) void()) {} \
template <class... _Args, \
class _Sig, \
class = decltype(static_cast<_Sig*>(&__cccl_self_t::__cccl_well_formed<_Args...>))> \
_LIBCUDACXX_HIDE_FROM_ABI static constexpr bool __cccl_is_satisfied(::__cccl_tag<_Args...>*, _Sig*) \
{ \
return true; \
} \
_LIBCUDACXX_HIDE_FROM_ABI static constexpr bool __cccl_is_satisfied(void*, ...) \
{ \
return false; \
} \
}
# endif

#endif // _CCCL_STD_VER >= 2014

#endif //_CUDA___CONCEPTS
#endif // _CUDA___CONCEPTS_CONCEPT_MACROS
Loading