2017-03-20 16:34:24 -05:00
|
|
|
/*
|
2021-07-02 16:46:49 -07:00
|
|
|
Copyright (c) 2015 - 2021 Advanced Micro Devices, Inc. All rights reserved.
|
2017-03-20 16:34:24 -05:00
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
*/
|
|
|
|
|
|
2017-03-17 17:17:12 +00:00
|
|
|
#pragma once
|
2017-04-07 14:06:31 -05:00
|
|
|
#include "concepts.hpp"
|
2017-03-17 17:17:12 +00:00
|
|
|
|
2018-03-12 11:29:03 +05:30
|
|
|
#include <type_traits> // For std::conditional, std::decay, std::enable_if,
|
|
|
|
|
// std::false_type, std result_of and std::true_type.
|
|
|
|
|
#include <utility> // For std::declval.
|
|
|
|
|
|
2025-08-20 16:28:06 +02:00
|
|
|
#ifdef __has_include // Check if __has_include is present
|
|
|
|
|
#if __has_include(<version>) // Check for version header
|
|
|
|
|
#include <version>
|
|
|
|
|
#if defined(__cpp_lib_is_invocable) && !defined(HIP_HAS_INVOCABLE)
|
|
|
|
|
#define HIP_HAS_INVOCABLE __cpp_lib_is_invocable
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(__cpp_lib_result_of_sfinae) && !defined(HIP_HAS_RESULT_OF_SFINAE)
|
|
|
|
|
#define HIP_HAS_RESULT_OF_SFINAE __cpp_lib_result_of_sfinae
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
2019-11-20 10:03:42 -06:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifndef HIP_HAS_INVOCABLE
|
|
|
|
|
#define HIP_HAS_INVOCABLE 0
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifndef HIP_HAS_RESULT_OF_SFINAE
|
|
|
|
|
#define HIP_HAS_RESULT_OF_SFINAE 0
|
|
|
|
|
#endif
|
|
|
|
|
|
2018-03-12 11:29:03 +05:30
|
|
|
namespace std { // TODO: these should be removed as soon as possible.
|
|
|
|
|
#if (__cplusplus < 201406L)
|
|
|
|
|
#if (__cplusplus < 201402L)
|
2025-08-20 16:28:06 +02:00
|
|
|
template <bool cond, typename T = void> using enable_if_t = typename enable_if<cond, T>::type;
|
2018-03-12 11:29:03 +05:30
|
|
|
template <bool cond, typename T, typename U>
|
|
|
|
|
using conditional_t = typename conditional<cond, T, U>::type;
|
2025-08-20 16:28:06 +02:00
|
|
|
template <typename T> using decay_t = typename decay<T>::type;
|
2018-03-12 11:29:03 +05:30
|
|
|
template <FunctionalProcedure F, typename... Ts>
|
|
|
|
|
using result_of_t = typename result_of<F(Ts...)>::type;
|
2025-08-20 16:28:06 +02:00
|
|
|
template <typename T> using remove_reference_t = typename remove_reference<T>::type;
|
2018-03-12 11:29:03 +05:30
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
} // namespace std
|
|
|
|
|
|
|
|
|
|
namespace hip_impl {
|
2025-08-20 16:28:06 +02:00
|
|
|
template <typename...> using void_t_ = void;
|
2018-03-12 11:29:03 +05:30
|
|
|
|
2019-11-20 10:03:42 -06:00
|
|
|
#if HIP_HAS_INVOCABLE
|
2025-08-20 16:28:06 +02:00
|
|
|
template <typename, typename = void> struct is_callable_impl;
|
2018-03-12 11:29:03 +05:30
|
|
|
|
|
|
|
|
template <FunctionalProcedure F, typename... Ts>
|
2019-11-20 10:03:42 -06:00
|
|
|
struct is_callable_impl<F(Ts...)> : std::is_invocable<F, Ts...> {};
|
|
|
|
|
#elif HIP_HAS_RESULT_OF_SFINAE
|
2025-08-20 16:28:06 +02:00
|
|
|
template <typename, typename = void> struct is_callable_impl : std::false_type {};
|
2018-03-12 11:29:03 +05:30
|
|
|
|
|
|
|
|
template <FunctionalProcedure F, typename... Ts>
|
2025-08-20 16:28:06 +02:00
|
|
|
struct is_callable_impl<F(Ts...), void_t_<typename std::result_of<F(Ts...)>::type> >
|
|
|
|
|
: std::true_type {};
|
2019-05-06 12:03:09 -04:00
|
|
|
#else
|
2019-11-20 10:03:42 -06:00
|
|
|
template <class Base, class T, class Derived>
|
2025-08-20 16:28:06 +02:00
|
|
|
auto simple_invoke(T Base::* pmd, Derived&& ref) -> decltype(static_cast<Derived&&>(ref).*pmd);
|
2024-07-10 15:30:15 -04:00
|
|
|
|
2019-11-20 10:03:42 -06:00
|
|
|
template <class PMD, class Pointer>
|
|
|
|
|
auto simple_invoke(PMD&& pmd, Pointer&& ptr)
|
2025-08-20 16:28:06 +02:00
|
|
|
-> decltype((*static_cast<Pointer&&>(ptr)).*static_cast<PMD&&>(pmd));
|
2019-11-20 10:03:42 -06:00
|
|
|
|
|
|
|
|
template <class Base, class T, class Derived>
|
2025-08-20 16:28:06 +02:00
|
|
|
auto simple_invoke(T Base::* pmd, const std::reference_wrapper<Derived>& ref)
|
|
|
|
|
-> decltype(ref.get().*pmd);
|
2024-07-10 15:30:15 -04:00
|
|
|
|
2019-11-20 10:03:42 -06:00
|
|
|
template <class Base, class T, class Derived, class... Args>
|
2025-08-20 16:28:06 +02:00
|
|
|
auto simple_invoke(T Base::* pmf, Derived&& ref, Args&&... args)
|
|
|
|
|
-> decltype((static_cast<Derived&&>(ref).*pmf)(static_cast<Args&&>(args)...));
|
2024-07-10 15:30:15 -04:00
|
|
|
|
2019-11-20 10:03:42 -06:00
|
|
|
template <class PMF, class Pointer, class... Args>
|
|
|
|
|
auto simple_invoke(PMF&& pmf, Pointer&& ptr, Args&&... args)
|
2025-08-20 16:28:06 +02:00
|
|
|
-> decltype(((*static_cast<Pointer&&>(ptr)).*
|
|
|
|
|
static_cast<PMF&&>(pmf))(static_cast<Args&&>(args)...));
|
2019-11-20 10:03:42 -06:00
|
|
|
|
|
|
|
|
template <class Base, class T, class Derived, class... Args>
|
2025-08-20 16:28:06 +02:00
|
|
|
auto simple_invoke(T Base::* pmf, const std::reference_wrapper<Derived>& ref, Args&&... args)
|
|
|
|
|
-> decltype((ref.get().*pmf)(static_cast<Args&&>(args)...));
|
2019-11-20 10:03:42 -06:00
|
|
|
|
2025-08-20 16:28:06 +02:00
|
|
|
template <class F, class... Ts>
|
|
|
|
|
auto simple_invoke(F&& f, Ts&&... xs) -> decltype(f(static_cast<Ts&&>(xs)...));
|
2019-05-06 12:03:09 -04:00
|
|
|
|
2025-08-20 16:28:06 +02:00
|
|
|
template <typename, typename = void> struct is_callable_impl : std::false_type {};
|
2019-05-06 12:03:09 -04:00
|
|
|
|
|
|
|
|
template <FunctionalProcedure F, typename... Ts>
|
2025-08-20 16:28:06 +02:00
|
|
|
struct is_callable_impl<F(Ts...),
|
|
|
|
|
void_t_<decltype(simple_invoke(std::declval<F>(), std::declval<Ts>()...))> >
|
2019-11-20 10:03:42 -06:00
|
|
|
: std::true_type {};
|
|
|
|
|
|
2018-03-12 11:29:03 +05:30
|
|
|
#endif
|
2019-11-20 10:03:42 -06:00
|
|
|
|
2025-08-20 16:28:06 +02:00
|
|
|
template <typename Call> struct is_callable : is_callable_impl<Call> {};
|
2018-03-12 11:29:03 +05:30
|
|
|
|
|
|
|
|
#define count_macro_args_impl_hip_(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, \
|
|
|
|
|
_14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, \
|
|
|
|
|
_26, _27, _28, _29, _30, _31, _n, ...) \
|
2025-08-20 16:28:06 +02:00
|
|
|
_n
|
2018-03-12 11:29:03 +05:30
|
|
|
#define count_macro_args_hip_(...) \
|
2025-08-20 16:28:06 +02:00
|
|
|
count_macro_args_impl_hip_(, ##__VA_ARGS__, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, \
|
|
|
|
|
18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
2018-03-12 11:29:03 +05:30
|
|
|
|
|
|
|
|
#define overloaded_macro_expand_hip_(macro, arg_cnt) macro##arg_cnt
|
|
|
|
|
#define overload_macro_impl_hip_(macro, arg_cnt) overloaded_macro_expand_hip_(macro, arg_cnt)
|
|
|
|
|
#define overload_macro_hip_(macro, ...) \
|
2025-08-20 16:28:06 +02:00
|
|
|
overload_macro_impl_hip_(macro, count_macro_args_hip_(__VA_ARGS__))(__VA_ARGS__)
|
2018-03-12 11:29:03 +05:30
|
|
|
} // namespace hip_impl
|