• 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_VERIF_PARSER_CALLABLE_H_
17 #define PANDA_VERIF_PARSER_CALLABLE_H_
18 
19 #include <utility>
20 #include <tuple>
21 
22 namespace panda::verifier {
23 /*
24 
25 this is lightweight analogue of std::function.
26 Type-erased holder of function, closure or object with operator().
27 
28 NB! it does not keep object contents, only pointers, so
29 a closure must be accessible during lifetime of
30 the callable<...> object.
31 
32 Motivation: in many cases using type-erased callable object
33 based on std::function is very heavy-weight: extra allocations,
34 data copying, vtbls  and so on.
35 So here is lightweight counterpart, using static type-erasing
36 without extra storage other than two explicit private pointers.
37 */
38 
39 template <typename Signature>
40 class callable;
41 
42 template <typename R, typename... Args>
43 class callable<R(Args...)> {
44     struct callable_type {
45         R operator()(Args...);
46     };
47     typedef R (callable_type::*method_type)(Args...);
48     typedef R (*function_type)(Args...);
49     callable_type *object {nullptr};
50     union method_union {
51         method_type m;
52         function_type f;
method_union(method_type method)53         method_union(method_type method) : m(method) {}
method_union(function_type function)54         method_union(function_type function) : f(function) {}
method_union()55         method_union() : m {nullptr} {}
56         ~method_union() = default;
57     } method;
58 
59 public:
60     using Result = R;
61     using Arguments = std::tuple<Args...>;
62 
63     callable() = default;
64     callable(const callable &) = default;
65     callable(callable &&) = default;
66     callable &operator=(const callable &) = default;
67     callable &operator=(callable &&) = default;
68     ~callable() = default;
69 
70     template <typename T, typename = decltype(static_cast<R (T::*)(Args...) const>(&T::operator()))>
callable(const T & obj)71     constexpr callable(const T &obj)
72         : object {reinterpret_cast<callable_type *>(&const_cast<T &>(obj))},
73           method {reinterpret_cast<method_type>(static_cast<R (T::*)(Args...) const>(&T::operator()))}
74     {
75     }
76 
77     template <typename T, typename = decltype(static_cast<R (T::*)(Args...)>(&T::operator()))>
callable(T & obj)78     constexpr callable(T &obj)
79         : object {reinterpret_cast<callable_type *>(&const_cast<T &>(obj))},
80           method {reinterpret_cast<method_type>(static_cast<R (T::*)(Args...)>(&T::operator()))}
81     {
82     }
83 
84     template <typename T>
callable(const T & obj,R (T::* param_method)(Args...)const)85     constexpr callable(const T &obj, R (T::*param_method)(Args...) const)
86         : object {reinterpret_cast<callable_type *>(&const_cast<T &>(obj))},
87           method {reinterpret_cast<method_type>(param_method)}
88     {
89     }
90 
91     template <typename T>
callable(T & obj,R (T::* param_method)(Args...))92     constexpr callable(T &obj, R (T::*param_method)(Args...))
93         : object {reinterpret_cast<callable_type *>(&const_cast<T &>(obj))},
94           method {reinterpret_cast<method_type>(param_method)}
95     {
96     }
97 
callable(function_type func)98     constexpr callable(function_type func) : object {nullptr}, method {func} {}
99 
operator()100     constexpr R operator()(Args... args) const
101     {
102         if (object == nullptr) {
103             return (method.f)(args...);
104         }
105         return (object->*(method.m))(args...);
106     }
107 
108     operator bool() const
109     {
110         return (method.m != nullptr) || (method.f != nullptr);
111     }
112 };
113 }  // namespace panda::verifier
114 
115 #endif  // PANDA_VERIF_PARSER_CALLABLE_H_
116