• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 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 PANDA_VERIFIER_UTIL_FUNCTION_TRAITS_
17 #define PANDA_VERIFIER_UTIL_FUNCTION_TRAITS_
18 
19 #include <tuple>
20 
21 namespace panda::verifier {
22 template <int...>
23 struct indices {
24 };
25 
26 template <int N, int... S>
27 struct gen_indices : gen_indices<N - 1, N - 1, S...> {
28 };
29 
30 template <int... S>
31 struct gen_indices<0, S...> {
32     typedef indices<S...> type;
33 };
34 
35 template <class F>
36 struct function_signature_helper;
37 
38 template <typename R, typename... Args>
39 struct function_signature_helper<R (*)(Args...)> : public function_signature_helper<R(Args...)> {
40 };
41 
42 template <typename R, typename F, typename... Args>
43 struct function_signature_helper<R (F::*)(Args...) const> : public function_signature_helper<R(Args...)> {
44 };
45 
46 template <typename R, typename F, typename... Args>
47 struct function_signature_helper<R (F::*)(Args...)> : public function_signature_helper<R(Args...)> {
48 };
49 
50 template <typename R, typename... Args>
51 struct function_signature_helper<R(Args...)> {
52     using return_type = R;
53     using args_tuple = std::tuple<Args...>;
54 
55     static constexpr std::size_t arity = sizeof...(Args);
56 
57     template <std::size_t N>
58     struct argument {
59         static_assert(N < arity, "invalid argument index");
60         using type = std::tuple_element_t<N, args_tuple>;
61     };
62 
63     template <std::size_t N>
64     using arg_type = typename argument<N>::type;
65 };
66 
67 template <typename F>
68 class function_signature : public function_signature_helper<decltype(&F::operator())> {
69     using base = function_signature_helper<decltype(&F::operator())>;
70 
71 public:
72     template <typename L, typename... Args>
73     static typename base::return_type call(L f, std::tuple<Args...> &&args)
74     {
75         return call_helper(f, std::forward(args), typename gen_indices<sizeof...(Args)>::type {});
76     }
77 
78 private:
79     template <typename L, typename A, int... S>
80     static typename base::return_type call_helper(L f, A &&a, indices<S...>)
81     {
82         return f(std::forward(std::get<S>(a))...);
83     }
84 };
85 
86 template <typename BinOp>
87 class n_ary {
88 public:
89     using sig = function_signature<BinOp>;
90 
91     using ret_type = std::decay_t<typename sig::return_type>;
92     using lhs_type = std::decay_t<typename sig::template argument<0>::type>;
93     using rhs_type = std::decay_t<typename sig::template argument<1>::type>;
94     static_assert(sig::arity == 0x2, "only binary operation is expected");
95     static_assert(std::is_same<lhs_type, rhs_type>::value, "argument types should be the same");
96     static_assert(std::is_same<ret_type, lhs_type>::value, "return value type should be the same as arguments one");
97 
98     using type = ret_type;
99 
100     n_ary(BinOp op) : binop {op} {}
101 
102     auto operator()(type lhs, type rhs)
103     {
104         return binop(lhs, rhs);
105     }
106 
107     template <typename... Args>
108     auto operator()(type lhs, Args &&... args)
109     {
110         return binop(lhs, operator()(std::forward<Args>(args)...));
111     }
112 
113     template <typename... Args>
114     auto operator()(std::tuple<Args...> &&args)
115     {
116         return call_helper(std::forward<std::tuple<Args...>>(args), typename gen_indices<sizeof...(Args)>::type {});
117     }
118 
119 private:
120     template <typename A, int... S>
121     auto call_helper(A &&a, indices<S...>)
122     {
123         return operator()(std::forward<std::tuple_element_t<S, A>>(std::get<S>(a))...);
124     }
125 
126     BinOp binop;
127 };
128 }  // namespace panda::verifier
129 
130 #endif  // !PANDA_VERIFIER_UTIL_FUNCTION_TRAITS_
131