File Coverage

src/panda/function_utils.h
Criterion Covered Total %
statement 44 47 93.6
branch 250 500 50.0
condition n/a
subroutine n/a
pod n/a
total 294 547 53.7


line stmt bran cond sub pod time code
1             #pragma once
2             #include "refcnt.h"
3             #include "traits.h"
4             #include
5              
6             namespace panda {
7              
8             template
9             class function;
10              
11             namespace function_details {
12 148           struct AnyFunction {
13 296 50         virtual ~AnyFunction() {}
14              
15 45           virtual const AnyFunction* get_base() const {
16 45           return this;
17             }
18             };
19             }
20              
21              
22             template
23 118           struct Ifunction : function_details::AnyFunction, virtual Refcnt {
24 118 50         virtual ~Ifunction() {}
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
25             virtual Ret operator()(Args...) = 0;
26             virtual bool equals(const function_details::AnyFunction* oth) const = 0;
27             };
28              
29             namespace function_details {
30              
31             template
32             class abstract_function {};
33              
34             template
35 6           class storage {
36             public:
37             template
38 86           explicit storage(F&& f) : func(std::forward(f)) {}
39              
40             std::remove_reference_t func;
41             };
42              
43             template
44             class callable {};
45              
46             template
47 2           class callable : public storage
48             {
49             public:
50             template
51 68           explicit callable(F&& f) : storage(std::forward(f)) {}
52              
53 26           Ret operator()(Self&, Args... args) {
54 26 50         return this->func(args...);
    50          
55             }
56             };
57              
58              
59             template
60             class callable : public storage
61             {
62             public:
63             template
64 4           explicit callable(F&& f) : storage(std::forward(f)) {}
65              
66 2           Ret operator()(Self& self, Args... args) {
67 2           return this->func(self, args...);
68             }
69             };
70              
71             template
72 20 50         class abstract_function : public Ifunction, public storage {
    50          
    50          
    50          
    50          
    50          
73             public:
74             template
75 6 50         explicit abstract_function(F&& f) : storage(std::forward(f)) {}
    50          
    50          
    50          
    50          
76              
77 5           Ret operator()(Args... args) override {
78             static_assert(std::is_convertiblefunc(args...)), Ret>::value, "return type mismatch");
79 5           return this->func(args...);
80             }
81              
82 5           bool equals(const AnyFunction* oth) const override {
83 5 50         auto foth = dynamic_cast*>(oth->get_base());
    50          
    50          
84 5 50         if (foth == nullptr) {
    50          
    50          
85 0           return false;
86             }
87              
88 5           return this->func == foth->func;
89             }
90             };
91              
92             template
93 144 50         class abstract_function : public Ifunction
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
94             , public callable::value, Ifunction, Args...>
95             {
96             public:
97             using Derfed = std::remove_reference_t;
98             using Caller = callable::value, Ifunction, Args...>;
99              
100             template
101 36 50         explicit abstract_function(F&& f) : Caller(std::forward(f)) {}
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
102              
103 28           Ret operator()(Args... args) override {
104 28 50         return Caller::operator()(*this, args...);
    50          
105             }
106              
107 6           bool equals(const AnyFunction* oth) const override {
108 6           return this->get_base() == oth->get_base();
109             }
110              
111             private:
112             template
113             Ret call(Args... args) {
114             return (this->template func.*meth)(args...);
115             }
116             };
117              
118              
119             template
120             class abstract_function : public Ifunction, public storage {
121             public:
122             using Func = FRet (*)(FArgs...);
123             explicit abstract_function(const Func& f) : storage(f) {}
124              
125             Ret operator()(Args... args) override {
126             return this->func(args...);
127             }
128              
129             bool equals(const AnyFunction* oth) const override {
130             auto foth = dynamic_cast*>(oth->get_base());
131             if (foth == nullptr) return false;
132              
133             return this->func == foth->func;
134             }
135             };
136              
137             template
138 4 50         struct function_caster : public Ifunction {
    50          
139             From src;
140             using Check = std::is_base_of;
141              
142 1 50         function_caster(From src) : src(src) {}
143              
144 1           Ret operator()(Args... args) override {
145 1           return src->operator()(args...);
146             }
147              
148 1           bool equals(const function_details::AnyFunction* oth) const override {
149 1           return src->equals(oth);
150             }
151              
152 0           const AnyFunction* get_base() const override {
153 0           return src->get_base();
154             }
155              
156              
157             };
158              
159             template
160             struct is_panda_function_t {
161             static constexpr bool value = false;
162             };
163              
164             template
165             struct is_panda_function_t> {
166             static constexpr bool value = true;
167             };
168              
169             template
170             auto make_abstract_function(Ret (*f)(Args...)) -> iptr> {
171             if (!f) return nullptr;
172             return new abstract_function(f);
173             }
174              
175             template
176             auto tmp_abstract_function(Ret (*f)(Args...)) -> abstract_function {
177             assert(f);
178             return abstract_function(f);
179             }
180              
181             template
182             bool IsComp = is_comparable>::value,
183             typename DeFunctor = std::remove_reference_t,
184             typename = std::enable_if_t&, Args...>::value ||
185             has_call_operator::value>,
186             typename = std::enable_if_t::value>,
187             typename = std::enable_if_t::value>>
188 40           iptr> make_abstract_function(Functor&& f) {
189 40 50         if (!bool_or(f, true)) return nullptr;
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
190 40 50         return new abstract_function(std::forward(f));
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
191             }
192              
193             template
194             bool IsComp = is_comparable>::value,
195             typename DeFunctor = std::remove_reference_t,
196             typename = std::enable_if_t&, Args...>::value ||
197             has_call_operator::value>,
198             typename = std::enable_if_t::value>,
199             typename = std::enable_if_t::value>>
200 2           abstract_function tmp_abstract_function (Functor&& f) {
201 2 50         assert(bool_or(f, true));
    50          
202 2           return abstract_function(std::forward(f));
203             }
204              
205             template
206             typename = std::enable_if_t, Args...>::value>>
207 1           auto make_abstract_function(const function& func) -> iptr> {
208 1 50         if (!func) return nullptr;
209 1 50         return new function_caster(func.func);
    50          
210             }
211              
212              
213             template
214             struct method : public Ifunction{
215             using Method = Ret (Class::*)(Args...);
216             using ifunction = Ifunction;
217              
218             method(Method method, iptr thiz = nullptr) : thiz(thiz), meth(method) {}
219             iptr bind(iptr thiz) {
220             this->thiz = thiz;
221             return iptr(this);
222             }
223              
224             Ret operator()(Args... args) override {
225             return (thiz.get()->*meth)(std::forward(args)...);
226             }
227              
228             bool equals(const AnyFunction* oth) const override {
229             auto moth = dynamic_cast*>(oth->get_base());
230             if (moth == nullptr) return false;
231              
232             return operator ==(*moth);
233             }
234              
235             bool operator==(const method& oth) const {
236             return thiz == oth.thiz && meth == oth.meth;
237             }
238              
239             bool operator !=(const method& oth) const {
240             return !operator ==(oth);
241             }
242              
243             explicit operator bool() const {
244             return thiz && meth;
245             }
246              
247             private:
248             iptr thiz;
249             Method meth;
250             };
251              
252             template
253             inline iptr> make_method(Ret (Class::*meth)(Args...), iptr thiz = nullptr) {
254             if (!meth) return nullptr;
255             return new method(meth, thiz);
256             }
257              
258             template
259             inline iptr> make_abstract_function(Ret (Class::*meth)(Args...), iptr thiz = nullptr) {
260             if (!meth) return nullptr;
261             return new method(meth, thiz);
262             }
263              
264             template
265             inline method tmp_abstract_function(Ret (Class::*meth)(Args...), iptr thiz = nullptr) {
266             assert(meth);
267             return method(meth, thiz);
268             }
269             }
270              
271             }