1 /************************************************************************************
2 *                                                                                   *
3 *   Copyright (c) 2014 - 2018 Axel Menzel <info@rttr.org>                           *
4 *                                                                                   *
5 *   This file is part of RTTR (Run Time Type Reflection)                            *
6 *   License: MIT License                                                            *
7 *                                                                                   *
8 *   Permission is hereby granted, free of charge, to any person obtaining           *
9 *   a copy of this software and associated documentation files (the "Software"),    *
10 *   to deal in the Software without restriction, including without limitation       *
11 *   the rights to use, copy, modify, merge, publish, distribute, sublicense,        *
12 *   and/or sell copies of the Software, and to permit persons to whom the           *
13 *   Software is furnished to do so, subject to the following conditions:            *
14 *                                                                                   *
15 *   The above copyright notice and this permission notice shall be included in      *
16 *   all copies or substantial portions of the Software.                             *
17 *                                                                                   *
18 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR      *
19 *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,        *
20 *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE     *
21 *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER          *
22 *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,   *
23 *   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE   *
24 *   SOFTWARE.                                                                       *
25 *                                                                                   *
26 *************************************************************************************/
27 
28 #ifndef RTTR_METHOD_WRAPPER_H_
29 #define RTTR_METHOD_WRAPPER_H_
30 
31 #include "rttr/detail/base/core_prerequisites.h"
32 #include "rttr/detail/method/method_wrapper_base.h"
33 #include "rttr/detail/misc/function_traits.h"
34 #include "rttr/detail/type/accessor_type.h"
35 #include "rttr/detail/method/method_accessor.h"
36 #include "rttr/detail/default_arguments/default_arguments.h"
37 #include "rttr/detail/default_arguments/invoke_with_defaults.h"
38 #include "rttr/detail/parameter_info/parameter_infos.h"
39 #include "rttr/argument.h"
40 #include "rttr/instance.h"
41 #include "rttr/variant.h"
42 #include "rttr/array_range.h"
43 #include "rttr/detail/visitor/visitor_iterator.h"
44 #include "rttr/detail/visitor/method_visitor_invoker.h"
45 
46 #include <functional>
47 #include <string>
48 #include <array>
49 
50 namespace rttr
51 {
52 namespace detail
53 {
54 
55 template<typename F, typename Declaring_Type, access_levels Acc_Level, typename Policy, typename Default_Args, typename Parameter_Infos, std::size_t Metadata_Count, typename Visitor_List>
56 class method_wrapper;
57 
58 /////////////////////////////////////////////////////////////////////////////////////////
59 /////////////////////////////////////////////////////////////////////////////////////////
60 /////////////////////////////////////////////////////////////////////////////////////////
61 
62 template<typename F, typename Declaring_Type, access_levels Acc_Level, typename Policy, typename... Param_Args, std::size_t Metadata_Count, typename Visitor_List>
63 class method_wrapper<F, Declaring_Type, Acc_Level, Policy, default_args<>, parameter_infos<Param_Args...>, Metadata_Count, Visitor_List> : public method_wrapper_base, public metadata_handler<Metadata_Count>
64 {
65     public:
method_wrapper(string_view name,F func_acc,std::array<metadata,Metadata_Count> metadata_list,parameter_infos<Param_Args...> param_infos)66         method_wrapper(string_view name,
67                        F func_acc,
68                        std::array<metadata, Metadata_Count> metadata_list,
69                        parameter_infos<Param_Args...> param_infos) RTTR_NOEXCEPT
70         :   method_wrapper_base(name, type::get<Declaring_Type>()),
71             metadata_handler<Metadata_Count>(std::move(metadata_list)),
72             m_func_acc(func_acc),
73             m_param_infos(std::move(param_infos)),
74             m_param_info_list(create_paramter_info_array(m_param_infos))
75         {
76             init();
77         }
78 
is_valid()79         bool is_valid()                                     const RTTR_NOEXCEPT { return true;                                            }
is_static()80         bool is_static()                                    const RTTR_NOEXCEPT { return method_accessor<F, Policy>::is_static();         }
get_return_type()81         type get_return_type()                              const RTTR_NOEXCEPT { return method_accessor<F, Policy>::get_return_type();   }
get_is_reference()82         std::vector<bool> get_is_reference()                const RTTR_NOEXCEPT { return method_accessor<F, Policy>::get_is_reference();  }
get_is_const()83         std::vector<bool> get_is_const()                    const RTTR_NOEXCEPT { return method_accessor<F, Policy>::get_is_const();      }
get_access_level()84         access_levels get_access_level()                    const RTTR_NOEXCEPT { return Acc_Level; }
get_parameter_infos()85         array_range<parameter_info> get_parameter_infos()   const RTTR_NOEXCEPT { return array_range<parameter_info>(const_cast<decltype(m_param_info_list)&>(m_param_info_list).data(),
86                                                                                                        m_param_info_list.size()); }
get_metadata(const variant & key)87         variant get_metadata(const variant& key)            const { return metadata_handler<Metadata_Count>::get_metadata(key); }
88 
invoke(instance & object)89         variant invoke(instance& object) const
90         {
91            return method_accessor<F, Policy>::invoke(m_func_acc, object);
92         }
invoke(instance & object,argument & arg1)93         variant invoke(instance& object, argument& arg1) const
94         {
95             return method_accessor<F, Policy>::invoke(m_func_acc, object, arg1);
96         }
invoke(instance & object,argument & arg1,argument & arg2)97         variant invoke(instance& object, argument& arg1, argument& arg2) const
98         {
99             return method_accessor<F, Policy>::invoke(m_func_acc, object, arg1, arg2);
100         }
invoke(instance & object,argument & arg1,argument & arg2,argument & arg3)101         variant invoke(instance& object, argument& arg1, argument& arg2, argument& arg3) const
102         {
103             return method_accessor<F, Policy>::invoke(m_func_acc, object, arg1, arg2, arg3);
104         }
invoke(instance & object,argument & arg1,argument & arg2,argument & arg3,argument & arg4)105         variant invoke(instance& object, argument& arg1, argument& arg2, argument& arg3, argument& arg4) const
106         {
107             return method_accessor<F, Policy>::invoke(m_func_acc, object, arg1, arg2, arg3, arg4);
108         }
invoke(instance & object,argument & arg1,argument & arg2,argument & arg3,argument & arg4,argument & arg5)109         variant invoke(instance& object, argument& arg1, argument& arg2, argument& arg3, argument& arg4, argument& arg5) const
110         {
111             return method_accessor<F, Policy>::invoke(m_func_acc, object, arg1, arg2, arg3, arg4, arg5);
112         }
invoke(instance & object,argument & arg1,argument & arg2,argument & arg3,argument & arg4,argument & arg5,argument & arg6)113         variant invoke(instance& object, argument& arg1, argument& arg2, argument& arg3, argument& arg4, argument& arg5, argument& arg6) const
114         {
115             return method_accessor<F, Policy>::invoke(m_func_acc, object, arg1, arg2, arg3, arg4, arg5, arg6);
116         }
117 
invoke_variadic(const instance & object,std::vector<argument> & args)118         variant invoke_variadic(const instance& object, std::vector<argument>& args) const
119         {
120             return method_accessor<F, Policy>::invoke_variadic(m_func_acc, object, args);
121         }
122 
visit(visitor & visitor,method meth)123         void visit(visitor& visitor, method meth) const RTTR_NOEXCEPT
124         {
125             auto obj = make_method_info<Declaring_Type, Policy, F>(meth, m_func_acc);
126             visitor_iterator<Visitor_List>::visit(visitor, make_method_visitor_invoker(obj));
127         }
128 
129     private:
130         F  m_func_acc;
131         parameter_infos<Param_Args...> m_param_infos;
132         std::array<parameter_info, sizeof...(Param_Args)> m_param_info_list;
133 };
134 
135 /////////////////////////////////////////////////////////////////////////////////////////
136 
137 template<typename F, typename Declaring_Type, access_levels Acc_Level, typename Policy, typename...Default_Args, typename...Param_Args, std::size_t Metadata_Count, typename Visitor_List>
138 class method_wrapper<F, Declaring_Type, Acc_Level, Policy, default_args<Default_Args...>, parameter_infos<Param_Args...>, Metadata_Count, Visitor_List> : public method_wrapper_base, public metadata_handler<Metadata_Count>
139 {
140     using method_type = typename detail::method_type<F>::type;
141     using arg_index_sequence = make_index_sequence<function_traits<F>::arg_count>;
142     using invoker_class = method_invoker<F, Policy, method_type, arg_index_sequence>;
143     using invoke_with_defaults = invoke_defaults_helper<invoker_class, F>;
144 
145     public:
method_wrapper(string_view name,F func_acc,std::array<metadata,Metadata_Count> metadata_list,default_args<Default_Args...> default_args,parameter_infos<Param_Args...> param_infos)146         method_wrapper(string_view name,
147                        F func_acc,
148                        std::array<metadata, Metadata_Count> metadata_list,
149                        default_args<Default_Args...> default_args,
150                        parameter_infos<Param_Args...> param_infos) RTTR_NOEXCEPT
151         :   method_wrapper_base(name, type::get<Declaring_Type>()),
152             metadata_handler<Metadata_Count>(std::move(metadata_list)),
153             m_func_acc(func_acc),
154             m_def_args(std::move(default_args)),
155             m_param_infos(std::move(param_infos)),
156             m_param_info_list(create_paramter_info_array(m_param_infos))
157         {
158             store_default_args_in_param_infos(m_param_infos, m_def_args);
159             init();
160         }
161 
is_valid()162         bool is_valid()                                     const RTTR_NOEXCEPT { return true;                                            }
is_static()163         bool is_static()                                    const RTTR_NOEXCEPT { return method_accessor<F, Policy>::is_static();         }
get_return_type()164         type get_return_type()                              const RTTR_NOEXCEPT { return method_accessor<F, Policy>::get_return_type();   }
get_is_reference()165         std::vector<bool> get_is_reference()                const RTTR_NOEXCEPT { return method_accessor<F, Policy>::get_is_reference();  }
get_is_const()166         std::vector<bool> get_is_const()                    const RTTR_NOEXCEPT { return method_accessor<F, Policy>::get_is_const();      }
get_access_level()167         access_levels get_access_level()                    const RTTR_NOEXCEPT { return Acc_Level; }
get_parameter_infos()168         array_range<parameter_info> get_parameter_infos()   const RTTR_NOEXCEPT { return array_range<parameter_info>(const_cast<decltype(m_param_info_list)&>(m_param_info_list).data(),
169                                                                                                        m_param_info_list.size()); }
get_metadata(const variant & key)170         variant get_metadata(const variant& key)            const { return metadata_handler<Metadata_Count>::get_metadata(key); }
171 
invoke(instance & object)172         variant invoke(instance& object) const
173         {
174             return invoke_with_defaults::invoke(m_func_acc, object, m_def_args.m_args);
175         }
invoke(instance & object,argument & arg1)176         variant invoke(instance& object, argument& arg1) const
177         {
178             return invoke_with_defaults::invoke(m_func_acc, object, m_def_args.m_args, arg1);
179         }
invoke(instance & object,argument & arg1,argument & arg2)180         variant invoke(instance& object, argument& arg1, argument& arg2) const
181         {
182             return invoke_with_defaults::invoke(m_func_acc, object, m_def_args.m_args, arg1, arg2);
183         }
invoke(instance & object,argument & arg1,argument & arg2,argument & arg3)184         variant invoke(instance& object, argument& arg1, argument& arg2, argument& arg3) const
185         {
186             return invoke_with_defaults::invoke(m_func_acc, object, m_def_args.m_args, arg1, arg2, arg3);
187         }
invoke(instance & object,argument & arg1,argument & arg2,argument & arg3,argument & arg4)188         variant invoke(instance& object, argument& arg1, argument& arg2, argument& arg3, argument& arg4) const
189         {
190             return invoke_with_defaults::invoke(m_func_acc, object, m_def_args.m_args, arg1, arg2, arg3, arg4);
191         }
invoke(instance & object,argument & arg1,argument & arg2,argument & arg3,argument & arg4,argument & arg5)192         variant invoke(instance& object, argument& arg1, argument& arg2, argument& arg3, argument& arg4, argument& arg5) const
193         {
194             return invoke_with_defaults::invoke(m_func_acc, object, m_def_args.m_args, arg1, arg2, arg3, arg4, arg5);
195         }
invoke(instance & object,argument & arg1,argument & arg2,argument & arg3,argument & arg4,argument & arg5,argument & arg6)196         variant invoke(instance& object, argument& arg1, argument& arg2, argument& arg3, argument& arg4, argument& arg5, argument& arg6) const
197         {
198             return invoke_with_defaults::invoke(m_func_acc, object, m_def_args.m_args, arg1, arg2, arg3, arg4, arg5, arg6);
199         }
200 
invoke_variadic(const instance & object,std::vector<argument> & args)201         variant invoke_variadic(const instance& object, std::vector<argument>& args) const
202         {
203             if (args.size() <= function_traits<F>::arg_count)
204                 return invoke_variadic_helper<invoke_with_defaults, arg_index_sequence>::invoke(args, m_func_acc, object, m_def_args.m_args);
205             else
206                 return variant();
207         }
208 
visit(visitor & visitor,method meth)209         void visit(visitor& visitor, method meth) const RTTR_NOEXCEPT
210         {
211             auto obj = make_method_info<Declaring_Type, Policy, F>(meth, m_func_acc);
212             visitor_iterator<Visitor_List>::visit(visitor, make_method_visitor_invoker(obj));
213         }
214 
215     private:
216         F                               m_func_acc;
217         default_args<Default_Args...>   m_def_args;
218         parameter_infos<Param_Args...>  m_param_infos;
219         std::array<parameter_info, sizeof...(Param_Args)> m_param_info_list;
220 };
221 
222 /////////////////////////////////////////////////////////////////////////////////////////
223 
224 template<typename F, typename Declaring_Type, access_levels Acc_Level, typename Policy, std::size_t Metadata_Count, typename Visitor_List>
225 class method_wrapper<F, Declaring_Type, Acc_Level, Policy, default_args<>, parameter_infos<>, Metadata_Count, Visitor_List> : public method_wrapper_base, public metadata_handler<Metadata_Count>
226 {
227     public:
method_wrapper(string_view name,F func_acc,std::array<metadata,Metadata_Count> metadata_list,parameter_infos<> param_infos)228         method_wrapper(string_view name,
229                        F func_acc,
230                        std::array<metadata, Metadata_Count> metadata_list,
231                        parameter_infos<> param_infos) RTTR_NOEXCEPT
232         :   method_wrapper_base(name, type::get<Declaring_Type>()),
233             metadata_handler<Metadata_Count>(std::move(metadata_list)),
234             m_func_acc(func_acc)
235         {
236             init();
237         }
238 
is_valid()239         bool is_valid()                                     const RTTR_NOEXCEPT { return true;                                            }
is_static()240         bool is_static()                                    const RTTR_NOEXCEPT { return method_accessor<F, Policy>::is_static();         }
get_return_type()241         type get_return_type()                              const RTTR_NOEXCEPT { return method_accessor<F, Policy>::get_return_type();   }
get_is_reference()242         std::vector<bool> get_is_reference()                const RTTR_NOEXCEPT { return method_accessor<F, Policy>::get_is_reference();  }
get_is_const()243         std::vector<bool> get_is_const()                    const RTTR_NOEXCEPT { return method_accessor<F, Policy>::get_is_const();      }
get_access_level()244         access_levels get_access_level()                    const RTTR_NOEXCEPT { return Acc_Level;                                       }
get_parameter_infos()245         array_range<parameter_info> get_parameter_infos()   const RTTR_NOEXCEPT { return array_range<parameter_info>();                   }
get_metadata(const variant & key)246         variant get_metadata(const variant& key)            const { return metadata_handler<Metadata_Count>::get_metadata(key); }
247 
invoke(instance & object)248         variant invoke(instance& object) const
249         {
250            return method_accessor<F, Policy>::invoke(m_func_acc, object);
251         }
invoke(instance & object,argument & arg1)252         variant invoke(instance& object, argument& arg1) const
253         {
254             return method_accessor<F, Policy>::invoke(m_func_acc, object, arg1);
255         }
invoke(instance & object,argument & arg1,argument & arg2)256         variant invoke(instance& object, argument& arg1, argument& arg2) const
257         {
258             return method_accessor<F, Policy>::invoke(m_func_acc, object, arg1, arg2);
259         }
invoke(instance & object,argument & arg1,argument & arg2,argument & arg3)260         variant invoke(instance& object, argument& arg1, argument& arg2, argument& arg3) const
261         {
262             return method_accessor<F, Policy>::invoke(m_func_acc, object, arg1, arg2, arg3);
263         }
invoke(instance & object,argument & arg1,argument & arg2,argument & arg3,argument & arg4)264         variant invoke(instance& object, argument& arg1, argument& arg2, argument& arg3, argument& arg4) const
265         {
266             return method_accessor<F, Policy>::invoke(m_func_acc, object, arg1, arg2, arg3, arg4);
267         }
invoke(instance & object,argument & arg1,argument & arg2,argument & arg3,argument & arg4,argument & arg5)268         variant invoke(instance& object, argument& arg1, argument& arg2, argument& arg3, argument& arg4, argument& arg5) const
269         {
270             return method_accessor<F, Policy>::invoke(m_func_acc, object, arg1, arg2, arg3, arg4, arg5);
271         }
invoke(instance & object,argument & arg1,argument & arg2,argument & arg3,argument & arg4,argument & arg5,argument & arg6)272         variant invoke(instance& object, argument& arg1, argument& arg2, argument& arg3, argument& arg4, argument& arg5, argument& arg6) const
273         {
274             return method_accessor<F, Policy>::invoke(m_func_acc, object, arg1, arg2, arg3, arg4, arg5, arg6);
275         }
276 
invoke_variadic(const instance & object,std::vector<argument> & args)277         variant invoke_variadic(const instance& object, std::vector<argument>& args) const
278         {
279             return method_accessor<F, Policy>::invoke_variadic(m_func_acc, object, args);
280         }
281 
visit(visitor & visitor,method meth)282         void visit(visitor& visitor, method meth) const RTTR_NOEXCEPT
283         {
284             auto obj = make_method_info<Declaring_Type, Policy, F>(meth, m_func_acc);
285             visitor_iterator<Visitor_List>::visit(visitor, make_method_visitor_invoker(obj));
286         }
287 
288     private:
289         F  m_func_acc;
290 };
291 
292 /////////////////////////////////////////////////////////////////////////////////////////
293 
294 template<typename F, typename Declaring_Type, access_levels Acc_Level, typename Policy, typename...Default_Args, std::size_t Metadata_Count, typename Visitor_List>
295 class method_wrapper<F, Declaring_Type, Acc_Level, Policy, default_args<Default_Args...>, parameter_infos<>, Metadata_Count, Visitor_List> : public method_wrapper_base, public metadata_handler<Metadata_Count>
296 {
297     using method_type = typename detail::method_type<F>::type;
298     using arg_index_sequence = make_index_sequence<function_traits<F>::arg_count>;
299     using invoker_class = method_invoker<F, Policy, method_type, arg_index_sequence>;
300     using invoke_with_defaults = invoke_defaults_helper<invoker_class, F>;
301 
302     public:
method_wrapper(string_view name,F func_acc,std::array<metadata,Metadata_Count> metadata_list,default_args<Default_Args...> default_args,parameter_infos<> param_infos)303         method_wrapper(string_view name,
304                        F func_acc,
305                        std::array<metadata, Metadata_Count> metadata_list,
306                        default_args<Default_Args...> default_args,
307                        parameter_infos<> param_infos)
308         :   method_wrapper_base(name, type::get<Declaring_Type>()),
309             metadata_handler<Metadata_Count>(std::move(metadata_list)),
310             m_func_acc(func_acc),
311             m_def_args(std::move(default_args))
312         {
313             init();
314         }
315 
is_valid()316         bool is_valid()                                     const RTTR_NOEXCEPT { return true;                                            }
is_static()317         bool is_static()                                    const RTTR_NOEXCEPT { return method_accessor<F, Policy>::is_static();         }
get_return_type()318         type get_return_type()                              const RTTR_NOEXCEPT { return method_accessor<F, Policy>::get_return_type();   }
get_is_reference()319         std::vector<bool> get_is_reference()                const RTTR_NOEXCEPT { return method_accessor<F, Policy>::get_is_reference();  }
get_is_const()320         std::vector<bool> get_is_const()                    const RTTR_NOEXCEPT { return method_accessor<F, Policy>::get_is_const();      }
get_access_level()321         access_levels get_access_level()                    const RTTR_NOEXCEPT { return Acc_Level;                                       }
get_parameter_infos()322         array_range<parameter_info> get_parameter_infos()   const RTTR_NOEXCEPT { return array_range<parameter_info>();                   }
get_metadata(const variant & key)323         variant get_metadata(const variant& key)            const { return metadata_handler<Metadata_Count>::get_metadata(key); }
324 
invoke(instance & object)325         variant invoke(instance& object) const
326         {
327             return invoke_with_defaults::invoke(m_func_acc, object, m_def_args.m_args);
328         }
invoke(instance & object,argument & arg1)329         variant invoke(instance& object, argument& arg1) const
330         {
331             return invoke_with_defaults::invoke(m_func_acc, object, m_def_args.m_args, arg1);
332         }
invoke(instance & object,argument & arg1,argument & arg2)333         variant invoke(instance& object, argument& arg1, argument& arg2) const
334         {
335             return invoke_with_defaults::invoke(m_func_acc, object, m_def_args.m_args, arg1, arg2);
336         }
invoke(instance & object,argument & arg1,argument & arg2,argument & arg3)337         variant invoke(instance& object, argument& arg1, argument& arg2, argument& arg3) const
338         {
339             return invoke_with_defaults::invoke(m_func_acc, object, m_def_args.m_args, arg1, arg2, arg3);
340         }
invoke(instance & object,argument & arg1,argument & arg2,argument & arg3,argument & arg4)341         variant invoke(instance& object, argument& arg1, argument& arg2, argument& arg3, argument& arg4) const
342         {
343             return invoke_with_defaults::invoke(m_func_acc, object, m_def_args.m_args, arg1, arg2, arg3, arg4);
344         }
invoke(instance & object,argument & arg1,argument & arg2,argument & arg3,argument & arg4,argument & arg5)345         variant invoke(instance& object, argument& arg1, argument& arg2, argument& arg3, argument& arg4, argument& arg5) const
346         {
347             return invoke_with_defaults::invoke(m_func_acc, object, m_def_args.m_args, arg1, arg2, arg3, arg4, arg5);
348         }
invoke(instance & object,argument & arg1,argument & arg2,argument & arg3,argument & arg4,argument & arg5,argument & arg6)349         variant invoke(instance& object, argument& arg1, argument& arg2, argument& arg3, argument& arg4, argument& arg5, argument& arg6) const
350         {
351             return invoke_with_defaults::invoke(m_func_acc, object, m_def_args.m_args, arg1, arg2, arg3, arg4, arg5, arg6);
352         }
353 
invoke_variadic(const instance & object,std::vector<argument> & args)354         variant invoke_variadic(const instance& object, std::vector<argument>& args) const
355         {
356             if (args.size() <= function_traits<F>::arg_count)
357                 return invoke_variadic_helper<invoke_with_defaults, arg_index_sequence>::invoke(args, m_func_acc, object, m_def_args.m_args);
358             else
359                 return variant();
360         }
361 
visit(visitor & visitor,method meth)362         void visit(visitor& visitor, method meth) const RTTR_NOEXCEPT
363         {
364             auto obj = make_method_info<Declaring_Type, Policy, F>(meth, m_func_acc);
365             visitor_iterator<Visitor_List>::visit(visitor, make_method_visitor_invoker(obj));
366         }
367 
368     private:
369         F                               m_func_acc;
370         default_args<Default_Args...>   m_def_args;
371 };
372 
373 /////////////////////////////////////////////////////////////////////////////////////////
374 
375 } // end namespace detail
376 } // end namespace rttr
377 
378 #endif // RTTR_METHOD_WRAPPER_H_
379