• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2024 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 ark::verifier {
22 template <int...>
23 struct Indices {
24 };
25 
26 template <int N, int... S>
27 struct GenIndices : GenIndices<N - 1, N - 1, S...> {
28 };
29 
30 template <int... S>
31 struct GenIndices<0, S...> {
32     using Type = Indices<S...>;
33 };
34 
35 template <class F>
36 struct FunctionSignatureHelper;
37 
38 template <typename R, typename... Args>
39 struct FunctionSignatureHelper<R (*)(Args...)> : public FunctionSignatureHelper<R(Args...)> {
40 };
41 
42 template <typename R, typename F, typename... Args>
43 struct FunctionSignatureHelper<R (F::*)(Args...) const> : public FunctionSignatureHelper<R(Args...)> {
44 };
45 
46 template <typename R, typename F, typename... Args>
47 struct FunctionSignatureHelper<R (F::*)(Args...)> : public FunctionSignatureHelper<R(Args...)> {
48 };
49 
50 template <typename R, typename... Args>
51 struct FunctionSignatureHelper<R(Args...)> {
52     using ReturnType = R;
53     using ArgsTuple = 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, ArgsTuple>;
61     };
62 
63     template <std::size_t N>
64     using ArgType = typename Argument<N>::Type;
65 };
66 
67 template <typename F>
68 class FunctionSignature : public FunctionSignatureHelper<decltype(&F::operator())> {
69     using Base = FunctionSignatureHelper<decltype(&F::operator())>;
70 
71 public:
72     template <typename L, typename... Args>
73     static typename Base::ReturnType Call(L f, std::tuple<Args...> &&args)
74     {
75         return call_helper(f, std::forward(args), typename GenIndices<sizeof...(Args)>::RetType {});
76     }
77 
78 private:
79     template <typename L, typename A, int... S>
80     static typename Base::ReturnType CallHelper(L f, A &&a, Indices<S...> /* unused */)
81     {
82         return f(std::forward(std::get<S>(a))...);
83     }
84 };
85 
86 template <typename BinOp>
87 class NAry {
88 public:
89     using Sig = FunctionSignature<BinOp>;
90 
91     using RetType = std::decay_t<typename Sig::ReturnType>;
92     using LhsType = std::decay_t<typename Sig::template Argument<0>::Type>;
93     using RhsType = 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<LhsType, RhsType>::value, "argument types should be the same");
96     static_assert(std::is_same<RetType, LhsType>::value, "return value type should be the same as arguments one");
97 
98     using Type = RetType;
99 
100     explicit NAry(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 CallHelper(std::forward<std::tuple<Args...>>(args), typename GenIndices<sizeof...(Args)>::Type {});
117     }
118 
119 private:
120     template <typename A, int... S>
121     auto CallHelper(A &&a, Indices<S...> /* unused */)
122     {
123         return operator()(std::forward<std::tuple_element_t<S, A>>(std::get<S>(a))...);
124     }
125 
126     BinOp binop_;
127 };
128 }  // namespace ark::verifier
129 
130 #endif  // !PANDA_VERIFIER_UTIL_FUNCTION_TRAITS_
131