//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. // //===----------------------------------------------------------------------===// // Modifications Copyright (c) 2025 Advanced Micro Devices, Inc. // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // template // concept invocable; #include #include #include #include #include "test_macros.h" using cuda::std::invocable; template __host__ __device__ constexpr bool check_invocable() { constexpr bool result = invocable; static_assert(invocable == result, ""); static_assert(invocable == result, ""); static_assert(invocable == result, ""); static_assert(invocable == result, ""); static_assert(invocable == result, ""); return result; } static_assert(check_invocable(), ""); static_assert(check_invocable(), ""); static_assert(check_invocable(), ""); static_assert(check_invocable(), ""); static_assert(check_invocable(), ""); static_assert(check_invocable(), ""); struct S; static_assert(check_invocable(), ""); static_assert(check_invocable(), ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); namespace function_objects { struct function_object { __host__ __device__ void operator()(); }; static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); struct const_function_object { __host__ __device__ void operator()(int) const; }; static_assert(invocable, ""); static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); struct volatile_function_object { __host__ __device__ void operator()(int, int) volatile; }; static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(invocable, ""); static_assert(!invocable, ""); struct cv_function_object { __host__ __device__ void operator()(int[]) const volatile; }; static_assert(invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); struct lvalue_function_object { __host__ __device__ void operator()() &; }; static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); struct lvalue_const_function_object { __host__ __device__ void operator()(int) const&; }; static_assert(invocable, ""); static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); struct lvalue_volatile_function_object { __host__ __device__ void operator()(int, int) volatile&; }; static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(invocable, ""); static_assert(!invocable, ""); struct lvalue_cv_function_object { __host__ __device__ void operator()(int[]) const volatile&; }; static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); // struct rvalue_function_object { __host__ __device__ void operator()() &&; }; static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); struct rvalue_const_function_object { __host__ __device__ void operator()(int) const&&; }; static_assert(invocable, ""); static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); struct rvalue_volatile_function_object { __host__ __device__ void operator()(int, int) volatile&&; }; static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); struct rvalue_cv_function_object { __host__ __device__ void operator()(int[]) const volatile&&; }; static_assert(invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); struct multiple_overloads { struct A {}; struct B { __host__ __device__ B(int); }; struct AB : A , B {}; struct O {}; __host__ __device__ void operator()(A) const; __host__ __device__ void operator()(B) const; }; static_assert(invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); } // namespace function_objects namespace pointer_to_member_functions { template __host__ __device__ constexpr bool check_member_is_invocable() { constexpr bool result = invocable; using uncv_t = cuda::std::remove_cvref_t; static_assert(invocable == result, ""); static_assert(invocable, Args...> == result, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); struct S2 {}; static_assert(!invocable, ""); return result; } static_assert(check_member_is_invocable(), ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(check_member_is_invocable(), ""); static_assert(!check_member_is_invocable(), ""); using unqualified = void (S::*)(); static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(check_member_is_invocable(), ""); using const_qualified = void (S::*)() const; static_assert(invocable, ""); static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(check_member_is_invocable(), ""); using volatile_qualified = void (S::*)() volatile; static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(check_member_is_invocable(), ""); using cv_qualified = void (S::*)() const volatile; static_assert(invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(check_member_is_invocable(), ""); using lvalue_qualified = void (S::*)() &; static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); #if !TEST_COMPILER(MSVC2019) static_assert(!invocable, ""); #endif // !TEST_COMPILER(MSVC2019) static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); #if TEST_STD_VER > 2017 static_assert(check_member_is_invocable(), ""); #endif // TEST_STD_VER > 2017 using lvalue_const_qualified = void (S::*)() const&; static_assert(invocable, ""); static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); #if TEST_STD_VER > 2017 static_assert(invocable, ""); static_assert(invocable, ""); #endif // TEST_STD_VER > 2017 static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(check_member_is_invocable(), ""); using lvalue_volatile_qualified = void (S::*)() volatile&; static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(invocable, ""); static_assert(!invocable, ""); #if !TEST_COMPILER(MSVC2019) static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); #endif // !TEST_COMPILER(MSVC2019) static_assert(check_member_is_invocable(), ""); using lvalue_cv_qualified = void (S::*)() const volatile&; static_assert(invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); #if !TEST_COMPILER(MSVC2019) static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); #endif // !TEST_COMPILER(MSVC2019) using rvalue_unqualified = void (S::*)() &&; static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); #if !TEST_COMPILER(MSVC2019) static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); #endif // !TEST_COMPILER(MSVC2019) using rvalue_const_unqualified = void (S::*)() const&&; static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); #if !TEST_COMPILER(MSVC2019) static_assert(invocable, ""); static_assert(invocable, ""); #endif // !TEST_COMPILER(MSVC2019) static_assert(!invocable, ""); static_assert(!invocable, ""); using rvalue_volatile_unqualified = void (S::*)() volatile&&; static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); #if !TEST_COMPILER(MSVC2019) static_assert(invocable, ""); static_assert(!invocable, ""); static_assert(invocable, ""); static_assert(!invocable, ""); #endif // !TEST_COMPILER(MSVC2019) using rvalue_cv_unqualified = void (S::*)() const volatile&&; static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); static_assert(!invocable, ""); #if !TEST_COMPILER(MSVC2019) static_assert(invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); static_assert(invocable, ""); #endif // !TEST_COMPILER(MSVC2019) } // namespace pointer_to_member_functions // Check the concept with closure types template __host__ __device__ constexpr bool is_invocable(F, Args&&...) { return invocable; } // execution space annotations on lambda require --extended-lambda flag with nvrtc #if !defined(TEST_COMPILER_NVRTC) && !defined(TEST_COMPILER_HIPRTC) static_assert(is_invocable([] {}), ""); static_assert(is_invocable([](int) {}, 0), ""); static_assert(is_invocable([](int) {}, 0L), ""); static_assert(!is_invocable([](int) {}, nullptr), ""); int i = 0; static_assert(is_invocable([](int&) {}, i), ""); #endif // !TEST_COMPILER(NVRTC) int main(int, char**) { return 0; }