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