3333#include < cuda/std/__type_traits/is_same.h>
3434#include < cuda/std/__type_traits/is_void.h>
3535#include < cuda/std/__type_traits/nat.h>
36+ #include < cuda/std/__type_traits/remove_cvref.h>
3637#include < cuda/std/__utility/declval.h>
3738#include < cuda/std/__utility/forward.h>
3839
3940#include < cuda/std/__cccl/prologue.h>
4041
4142_CCCL_BEGIN_NAMESPACE_CUDA_STD
4243
44+ namespace __detail
45+ {
46+
47+ #if _CCCL_CUDA_COMPILER(NVCC) && defined(__CUDACC_EXTENDED_LAMBDA__) && !_CCCL_DEVICE_COMPILATION() \
48+ && (defined (__nv_is_extended_device_lambda_closure_type) \
49+ || defined (__nv_is_extended_host_device_lambda_closure_type))
50+ template <class _Fn >
51+ _CCCL_INLINE_VISIBILITY constexpr bool __disallow_extended_lambda_invocability_v =
52+ # if defined(__nv_is_extended_device_lambda_closure_type)
53+ __nv_is_extended_device_lambda_closure_type (remove_cvref_t <_Fn>) ||
54+ # else
55+ false ||
56+ # endif
57+ # if defined(__nv_is_extended_host_device_lambda_closure_type)
58+ __nv_is_extended_host_device_lambda_closure_type (remove_cvref_t <_Fn>);
59+ # else
60+ false ;
61+ # endif
62+ #else
63+ template <class >
64+ _CCCL_INLINE_VISIBILITY constexpr bool __disallow_extended_lambda_invocability_v = false ;
65+ #endif
66+
67+ } // namespace __detail
68+
4369struct __any
4470{
4571 _CCCL_API inline __any (...);
@@ -214,17 +240,35 @@ struct _CCCL_TYPE_VISIBILITY_DEFAULT invoke_result //
214240
215241template <class _Fn, class... _Args>
216242struct _CCCL_TYPE_VISIBILITY_DEFAULT is_invocable : bool_constant<__is_invocable<_Fn, _Args...>>
217- {};
243+ {
244+ #if _CCCL_CUDA_COMPILER(NVCC) && defined(__CUDACC_EXTENDED_LAMBDA__) && !_CCCL_DEVICE_COMPILATION() \
245+ && (defined(__nv_is_extended_device_lambda_closure_type) \
246+ || defined(__nv_is_extended_host_device_lambda_closure_type))
247+ static_assert(!__detail::__disallow_extended_lambda_invocability_v<_Fn>,
248+ " Attempt to use an extended __device__ or __host__ __device__ lambda in a context "
249+ " that requires querying its invocability in host code. Use a named function object or "
250+ " cuda::proclaim_return_type instead." );
251+ #endif
252+ };
218253
219254template <class _Ret, class _Fn, class... _Args>
220255struct _CCCL_TYPE_VISIBILITY_DEFAULT is_invocable_r : bool_constant<__is_invocable_r<_Ret, _Fn, _Args...>>
221- {};
256+ {
257+ #if _CCCL_CUDA_COMPILER(NVCC) && defined(__CUDACC_EXTENDED_LAMBDA__) && !_CCCL_DEVICE_COMPILATION() \
258+ && (defined(__nv_is_extended_device_lambda_closure_type) \
259+ || defined(__nv_is_extended_host_device_lambda_closure_type))
260+ static_assert(!__detail::__disallow_extended_lambda_invocability_v<_Fn>,
261+ " Attempt to use an extended __device__ or __host__ __device__ lambda in a context "
262+ " that requires querying its invocability in host code. Use a named function object or "
263+ " cuda::proclaim_return_type instead." );
264+ #endif
265+ };
222266
223267template <class _Fn, class... _Args>
224- inline constexpr bool is_invocable_v = __is_invocable <_Fn, _Args...>;
268+ inline constexpr bool is_invocable_v = is_invocable <_Fn, _Args...>::value ;
225269
226270template <class _Ret, class _Fn, class... _Args>
227- inline constexpr bool is_invocable_r_v = __is_invocable_r <_Ret, _Fn, _Args...>;
271+ inline constexpr bool is_invocable_r_v = is_invocable_r <_Ret, _Fn, _Args...>::value ;
228272
229273// is_nothrow_invocable
230274
@@ -243,22 +287,40 @@ template <class _Ret, class _Fp, class... _Args>
243287inline constexpr bool __nothrow_invocable_r_imp<true, true, _Ret, _Fp, _Args...> =
244288 noexcept(::cuda::std::__invoke(::cuda::std::declval<_Fp>(), ::cuda::std::declval<_Args>()...));
245289
246- template <class _Fp, class... _Args>
247- inline constexpr bool is_nothrow_invocable_v =
248- __nothrow_invocable_r_imp<__is_invocable<_Fp, _Args...>, true, void, _Fp, _Args...>;
249-
250- template <class _Ret, class _Fp, class... _Args>
251- inline constexpr bool is_nothrow_invocable_r_v =
252- __nothrow_invocable_r_imp<__is_invocable_r<_Ret, _Fp, _Args...>, is_void_v<_Ret>, _Ret, _Fp, _Args...>;
253-
254290template <class _Fn, class... _Args>
255- struct _CCCL_TYPE_VISIBILITY_DEFAULT is_nothrow_invocable : bool_constant<is_nothrow_invocable_v<_Fn, _Args...>>
256- {};
291+ struct _CCCL_TYPE_VISIBILITY_DEFAULT is_nothrow_invocable
292+ : bool_constant<__nothrow_invocable_r_imp<__is_invocable<_Fn, _Args...>, true, void, _Fn, _Args...>>
293+ {
294+ #if _CCCL_CUDA_COMPILER(NVCC) && defined(__CUDACC_EXTENDED_LAMBDA__) && !_CCCL_DEVICE_COMPILATION() \
295+ && (defined(__nv_is_extended_device_lambda_closure_type) \
296+ || defined(__nv_is_extended_host_device_lambda_closure_type))
297+ static_assert(!__detail::__disallow_extended_lambda_invocability_v<_Fn>,
298+ " Attempt to use an extended __device__ or __host__ __device__ lambda in a context "
299+ " that requires querying its invocability in host code. Use a named function object or "
300+ " cuda::proclaim_return_type instead." );
301+ #endif
302+ };
257303
258304template <class _Ret, class _Fn, class... _Args>
259- struct _CCCL_TYPE_VISIBILITY_DEFAULT
260- is_nothrow_invocable_r : bool_constant<is_nothrow_invocable_r_v<_Ret, _Fn, _Args...>>
261- {};
305+ struct _CCCL_TYPE_VISIBILITY_DEFAULT is_nothrow_invocable_r
306+ : bool_constant<
307+ __nothrow_invocable_r_imp<__is_invocable_r<_Ret, _Fn, _Args...>, is_void_v<_Ret>, _Ret, _Fn, _Args...>>
308+ {
309+ #if _CCCL_CUDA_COMPILER(NVCC) && defined(__CUDACC_EXTENDED_LAMBDA__) && !_CCCL_DEVICE_COMPILATION() \
310+ && (defined(__nv_is_extended_device_lambda_closure_type) \
311+ || defined(__nv_is_extended_host_device_lambda_closure_type))
312+ static_assert(!__detail::__disallow_extended_lambda_invocability_v<_Fn>,
313+ " Attempt to use an extended __device__ or __host__ __device__ lambda in a context "
314+ " that requires querying its invocability in host code. Use a named function object or "
315+ " cuda::proclaim_return_type instead." );
316+ #endif
317+ };
318+
319+ template <class _Fp, class... _Args>
320+ inline constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<_Fp, _Args...>::value;
321+
322+ template <class _Ret, class _Fp, class... _Args>
323+ inline constexpr bool is_nothrow_invocable_r_v = is_nothrow_invocable_r<_Ret, _Fp, _Args...>::value;
262324
263325// Not going directly through __invoke_result_t because we want the additional device lambda checks in invoke_result
264326template <class _Fn, class... _Args>
0 commit comments