1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef HIVIEW_NAPI_UTIL
17 #define HIVIEW_NAPI_UTIL
18 #include <utility>
19 
20 namespace util {
21 template <typename ReturnType, typename... Args>
22 struct function_traits_defs {
23     static constexpr size_t arity = sizeof...(Args);
24 
25     using result_type = ReturnType;
26 
27     template <size_t i>
28     struct arg {
29         using type = typename std::tuple_element<i, std::tuple<Args...>>::type;
30     };
31 };
32 
33 template <typename T>
34 struct function_traits_impl;
35 
36 template <typename ReturnType, typename... Args>
37 struct function_traits_impl<ReturnType(Args...)>
38     : function_traits_defs<ReturnType, Args...> {};
39 
40 template <typename ReturnType, typename... Args>
41 struct function_traits_impl<ReturnType(*)(Args...)>
42     : function_traits_defs<ReturnType, Args...> {};
43 
44 template <typename ClassType, typename ReturnType, typename... Args>
45 struct function_traits_impl<ReturnType(ClassType::*)(Args...)>
46     : function_traits_defs<ReturnType, Args...> {};
47 
48 template <typename ClassType, typename ReturnType, typename... Args>
49 struct function_traits_impl<ReturnType(ClassType::*)(Args...) const>
50     : function_traits_defs<ReturnType, Args...> {};
51 
52 template <typename ClassType, typename ReturnType, typename... Args>
53 struct function_traits_impl<ReturnType(ClassType::*)(Args...) const&>
54     : function_traits_defs<ReturnType, Args...> {};
55 
56 template <typename ClassType, typename ReturnType, typename... Args>
57 struct function_traits_impl<ReturnType(ClassType::*)(Args...) const&&>
58     : function_traits_defs<ReturnType, Args...> {};
59 
60 template <typename ClassType, typename ReturnType, typename... Args>
61 struct function_traits_impl<ReturnType(ClassType::*)(Args...) volatile>
62     : function_traits_defs<ReturnType, Args...> {};
63 
64 template <typename ClassType, typename ReturnType, typename... Args>
65 struct function_traits_impl<ReturnType(ClassType::*)(Args...) volatile&>
66     : function_traits_defs<ReturnType, Args...> {};
67 
68 template <typename ClassType, typename ReturnType, typename... Args>
69 struct function_traits_impl<ReturnType(ClassType::*)(Args...) volatile&&>
70     : function_traits_defs<ReturnType, Args...> {};
71 
72 template <typename ClassType, typename ReturnType, typename... Args>
73 struct function_traits_impl<ReturnType(ClassType::*)(Args...) const volatile>
74     : function_traits_defs<ReturnType, Args...> {};
75 
76 template <typename ClassType, typename ReturnType, typename... Args>
77 struct function_traits_impl<ReturnType(ClassType::*)(Args...) const volatile&>
78     : function_traits_defs<ReturnType, Args...> {};
79 
80 template <typename ClassType, typename ReturnType, typename... Args>
81 struct function_traits_impl<ReturnType(ClassType::*)(Args...) const volatile&&>
82     : function_traits_defs<ReturnType, Args...> {};
83 
84 template <typename T, typename V = void>
85 struct function_traits
86     : function_traits_impl<T> {};
87 
88 template <typename T>
89 struct function_traits<T, decltype((void)&T::operator())>
90     : function_traits_impl<decltype(&T::operator())> {};
91 
92 template <size_t... Indices>
93 struct indices {
94     using next = indices<Indices..., sizeof...(Indices)>;
95 };
96 template <size_t N>
97 struct build_indices {
98     using type = typename build_indices<N - 1>::type::next;
99 };
100 template <>
101 struct build_indices<0> {
102     using type = indices<>;
103 };
104 template <size_t N>
105 using BuildIndices = typename build_indices<N>::type;
106 
107 namespace details {
108 template <typename FuncType,
109           typename VecType,
110           size_t... I,
111           typename Traits = function_traits<FuncType>,
112           typename ReturnT = typename Traits::result_type>
113 ReturnT do_call(FuncType& func, VecType& args, indices<I...>)
114 {
115     return func(args[I]...);
116 }
117 }  // namespace details
118 
119 template <
120     typename FuncType,
121     typename VecType,
122     typename Traits = function_traits<FuncType>,
123     typename ReturnT = typename Traits::result_type>
124 ReturnT unpack_caller(FuncType& func, VecType& args)
125 {
126     return details::do_call(func, args, BuildIndices<Traits::arity>());
127 }
128 } // namespace util
129 #endif // HIVIEW_NAPI_UTIL
130