parameter_infos.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  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. #ifndef RTTR_PARAMETER_INFOS_H_
  28. #define RTTR_PARAMETER_INFOS_H_
  29. #include "rttr/detail/base/core_prerequisites.h"
  30. #include "rttr/detail/parameter_info/parameter_info_wrapper.h"
  31. #include "rttr/detail/default_arguments/default_arguments.h"
  32. #include "rttr/parameter_info.h"
  33. namespace rttr
  34. {
  35. namespace detail
  36. {
  37. /////////////////////////////////////////////////////////////////////////////////////////
  38. template<typename...T>
  39. struct parameter_infos
  40. {
  41. parameter_infos() {}
  42. parameter_infos(T&&... args) : m_param_infos(std::forward<T>(args)...) {}
  43. std::tuple<T...> m_param_infos;
  44. RTTR_STATIC_CONSTEXPR std::size_t count = sizeof...(T);
  45. };
  46. template<>
  47. struct parameter_infos<>
  48. {
  49. parameter_infos() {}
  50. std::tuple<> m_param_infos;
  51. RTTR_STATIC_CONSTEXPR std::size_t count = 0;
  52. };
  53. /////////////////////////////////////////////////////////////////////////////////////////
  54. /////////////////////////////////////////////////////////////////////////////////////////
  55. /////////////////////////////////////////////////////////////////////////////////////////
  56. template<typename...Args>
  57. using has_param_names = std::integral_constant<bool, !std::is_same<null_type, find_if_t<is_parameter_names, Args...>>::value>;
  58. template<typename...TArgs>
  59. using count_param_names = count_if<is_parameter_names, raw_type_t<TArgs>... >;
  60. template<typename Args, typename Enable = void>
  61. struct param_names_count_impl;
  62. template<typename...Args>
  63. struct param_names_count_impl<type_list<Args...>, enable_if_t<has_param_names<Args...>::value>>
  64. {
  65. RTTR_STATIC_CONSTEXPR std::size_t count = find_if_t<is_parameter_names, Args...>::count;
  66. };
  67. template<typename...Args>
  68. struct param_names_count_impl<type_list<Args...>, enable_if_t<!has_param_names<Args...>::value>>
  69. {
  70. RTTR_STATIC_CONSTEXPR std::size_t count = 0;
  71. };
  72. template<typename...Args>
  73. using param_names_count = std::integral_constant<std::size_t, param_names_count_impl<type_list<Args...>>::count>;
  74. /////////////////////////////////////////////////////////////////////////////////////////
  75. /////////////////////////////////////////////////////////////////////////////////////////
  76. /////////////////////////////////////////////////////////////////////////////////////////
  77. template<typename T>
  78. static RTTR_INLINE
  79. parameter_info create_param_info(const T& data)
  80. {
  81. return parameter_info(&data);
  82. }
  83. template<std::size_t... Indices, typename...T>
  84. static RTTR_INLINE std::array<parameter_info, sizeof...(T)>
  85. create_paramter_info_array_impl(index_sequence<Indices...>, const parameter_infos<T...>& param_infos)
  86. {
  87. return { {create_param_info(std::get<Indices>(param_infos.m_param_infos))...} };
  88. };
  89. // MSVC 2015 cannot handle sizeof...(),
  90. // I retrieve a fatal error C1001: An internal error has occurred in the compiler.
  91. // (compiler file 'msc1.cpp', line 1421)
  92. // MSVC 2013 can handle it...
  93. template<typename...T, std::size_t Size = sizeof...(T)>
  94. static RTTR_INLINE std::array<parameter_info, Size>
  95. create_paramter_info_array(const parameter_infos<T...>& param_infos)
  96. {
  97. return create_paramter_info_array_impl(make_index_sequence<Size>(), param_infos);
  98. };
  99. /////////////////////////////////////////////////////////////////////////////////////////
  100. /////////////////////////////////////////////////////////////////////////////////////////
  101. /////////////////////////////////////////////////////////////////////////////////////////
  102. template<typename F, typename Has_Name, typename Default_Type_List, typename Indices>
  103. struct param_info_creater_func_impl;
  104. template<typename F, typename Has_Name, typename Default_Type_List, std::size_t... Arg_Count>
  105. struct param_info_creater_func_impl<F, Has_Name, Default_Type_List, index_sequence<Arg_Count...>>
  106. {
  107. using type = parameter_infos< parameter_info_wrapper<param_types_t<F, Arg_Count>, Arg_Count, Has_Name,
  108. type_list_element_t<Arg_Count, Default_Type_List> >...>;
  109. };
  110. /////////////////////////////////////////////////////////////////////////////////////////
  111. template<typename Ctor_Args_List, typename Has_Name, typename Default_Type_List, typename Indices>
  112. struct param_info_creater_ctor_impl;
  113. template<typename Ctor_Args_List, typename Has_Name, typename Default_Type_List, std::size_t... Arg_Count>
  114. struct param_info_creater_ctor_impl<Ctor_Args_List, Has_Name, Default_Type_List, index_sequence<Arg_Count...>>
  115. {
  116. using type = parameter_infos< parameter_info_wrapper<type_list_element_t<Arg_Count, Ctor_Args_List>, Arg_Count, Has_Name,
  117. type_list_element_t<Arg_Count, Default_Type_List> >...>;
  118. };
  119. /////////////////////////////////////////////////////////////////////////////////////////
  120. template<typename T, typename Acc_Type, typename Has_Name, typename Default_Type_List, typename Enable = void>
  121. struct param_info_creater;
  122. // for functions
  123. template<typename F, typename Acc_Type, typename Has_Name, typename...Def_Args>
  124. struct param_info_creater<type_list<F>, Acc_Type, Has_Name, type_list<Def_Args...>, enable_if_t< std::is_same<Acc_Type, function_type>::value >>
  125. {
  126. using new_default_list = push_front_n_t<void, type_list<Def_Args...>, function_traits<F>::arg_count - sizeof...(Def_Args)>;
  127. using idx_seq = make_index_sequence< function_traits<F>::arg_count>;
  128. using type = typename param_info_creater_func_impl<F, Has_Name, new_default_list, idx_seq>::type;
  129. };
  130. // ctor with one argument
  131. template<typename T, typename Has_Name, typename...Def_Args>
  132. struct param_info_creater<type_list<T>, constructor_type, Has_Name, type_list<Def_Args...>, enable_if_t< is_one_argument<T>::value >>
  133. {
  134. static_assert(sizeof...(Def_Args) < 2, "Invalid 'Def_Args' size.");
  135. using new_default_list = push_front_n_t<void, type_list<Def_Args...>, 1 - sizeof...(Def_Args)>;
  136. using idx_seq = make_index_sequence<1>;
  137. using type = typename param_info_creater_ctor_impl<type_list<T>, Has_Name, new_default_list, idx_seq>::type;
  138. };
  139. // ctor with zero or more then one argument
  140. template<typename Has_Name, typename...Ctor_Args, typename...Def_Args>
  141. struct param_info_creater<type_list<Ctor_Args...>, constructor_type, Has_Name, type_list<Def_Args...>, enable_if_t< !is_one_argument<Ctor_Args...>::value >>
  142. {
  143. static_assert(sizeof...(Ctor_Args) >= sizeof...(Def_Args), "Invalid 'Def_Args' size.");
  144. using new_default_list = push_front_n_t<void, type_list<Def_Args...>, sizeof...(Ctor_Args) - sizeof...(Def_Args)>;
  145. using idx_seq = make_index_sequence< sizeof...(Ctor_Args) >;
  146. using type = typename param_info_creater_ctor_impl<type_list<Ctor_Args...>, Has_Name, new_default_list, idx_seq>::type;
  147. };
  148. template<typename Acc_Args, typename Acc_Type, typename Has_Name, typename Def_Args>
  149. using param_info_creater_t = typename param_info_creater<Acc_Args, Acc_Type, Has_Name, Def_Args>::type;
  150. /////////////////////////////////////////////////////////////////////////////////////////
  151. /////////////////////////////////////////////////////////////////////////////////////////
  152. /////////////////////////////////////////////////////////////////////////////////////////
  153. template<typename Acc_Args, typename Acc_Type, typename Def_List, typename Param_Names, std::size_t... Indices>
  154. static RTTR_INLINE
  155. param_info_creater_t<Acc_Args, Acc_Type, has_param_name, Def_List>
  156. create_param_infos_and_store_names(index_sequence<Indices...>, Param_Names& names)
  157. {
  158. return param_info_creater_t<Acc_Args, Acc_Type, has_param_name, Def_List>{string_view(std::get<Indices>(names.m_param_names))...};
  159. }
  160. /////////////////////////////////////////////////////////////////////////////////////////
  161. /////////////////////////////////////////////////////////////////////////////////////////
  162. /////////////////////////////////////////////////////////////////////////////////////////
  163. template<typename Acc_Args, typename Acc_Type, typename...TArgs, typename T_Def = as_type_list_t<typename find_default_args_t<get_default_args_t<TArgs...>, Acc_Args, Acc_Type>::default_types_func>>
  164. static RTTR_INLINE
  165. enable_if_t< !has_param_names<TArgs...>::value && has_default_types<Acc_Args, type_list<TArgs...>, Acc_Type>::value, param_info_creater_t<Acc_Args, Acc_Type, no_param_name, T_Def>>
  166. create_param_infos(TArgs&&... args)
  167. {
  168. return param_info_creater_t<Acc_Args, Acc_Type, no_param_name, T_Def>();
  169. }
  170. /////////////////////////////////////////////////////////////////////////////////////////
  171. template<typename Acc_Args, typename Acc_Type, typename...TArgs>
  172. static RTTR_INLINE
  173. enable_if_t< !has_param_names<TArgs...>::value && !has_default_types<Acc_Args, type_list<TArgs...>, Acc_Type>::value, param_info_creater_t<Acc_Args, Acc_Type, no_param_name, type_list<> >>
  174. create_param_infos(TArgs&&... args)
  175. {
  176. return param_info_creater_t<Acc_Args, Acc_Type, no_param_name, type_list<> >();
  177. }
  178. /////////////////////////////////////////////////////////////////////////////////////////
  179. template<typename Acc_Args, typename Acc_Type, typename...TArgs, typename T_Def = as_type_list_t<typename find_default_args_t<get_default_args_t<TArgs...>, Acc_Args, Acc_Type>::default_types_func>>
  180. static RTTR_INLINE
  181. enable_if_t< has_param_names<TArgs...>::value && has_default_types<Acc_Args, type_list<TArgs...>, Acc_Type>::value, param_info_creater_t<Acc_Args, Acc_Type, has_param_name, T_Def>>
  182. create_param_infos(TArgs&&... args)
  183. {
  184. using Param_Type = find_if_t<is_parameter_names, TArgs...>;
  185. auto result = forward_to_array<Param_Type>(std::forward<TArgs>(args)...);
  186. return create_param_infos_and_store_names<Acc_Args, Acc_Type, T_Def>(make_index_sequence<Param_Type::count>(), result[0]);
  187. }
  188. /////////////////////////////////////////////////////////////////////////////////////////
  189. template<typename Acc_Args, typename Acc_Type, typename...TArgs>
  190. static RTTR_INLINE
  191. enable_if_t< has_param_names<TArgs...>::value && !has_default_types<Acc_Args, type_list<TArgs...>, Acc_Type>::value, param_info_creater_t<Acc_Args, Acc_Type, has_param_name, type_list<> >>
  192. create_param_infos(TArgs&&... args)
  193. {
  194. using Param_Type = find_if_t<is_parameter_names, TArgs...>;
  195. auto result = forward_to_array<Param_Type>(std::forward<TArgs>(args)...);
  196. return create_param_infos_and_store_names<Acc_Args, Acc_Type, type_list<>>(make_index_sequence<Param_Type::count>(), result[0]);
  197. }
  198. /////////////////////////////////////////////////////////////////////////////////////////
  199. /////////////////////////////////////////////////////////////////////////////////////////
  200. /////////////////////////////////////////////////////////////////////////////////////////
  201. template<typename Param_Arg, typename Default_Args>
  202. static RTTR_INLINE void store_default_value(Param_Arg& param_info, const Default_Args& def_arg)
  203. {
  204. param_info.set_default_value(&def_arg);
  205. }
  206. /////////////////////////////////////////////////////////////////////////////////////////
  207. template<typename Indices_Defaults, typename Indices_Params>
  208. struct store_default_args_helper;
  209. template<std::size_t D_Index, std::size_t...D_Indices, std::size_t P_Index, std::size_t...P_Indices>
  210. struct store_default_args_helper<index_sequence<D_Index, D_Indices...>, index_sequence<P_Index, P_Indices...>>
  211. {
  212. template<typename...Default_Args, typename...Param_Args>
  213. static RTTR_INLINE
  214. void perform(parameter_infos<Param_Args...>& param_infos, const default_args<Default_Args...>& def_args)
  215. {
  216. store_default_value(std::get<P_Index>(param_infos.m_param_infos), std::get<D_Index>(def_args.m_args));
  217. store_default_args_helper<index_sequence<D_Indices...>, index_sequence<P_Indices...>>::perform(param_infos, def_args);
  218. }
  219. };
  220. template<>
  221. struct store_default_args_helper<index_sequence<>, index_sequence<>>
  222. {
  223. template<typename...Default_Args, typename...Param_Args>
  224. static RTTR_INLINE
  225. void perform(parameter_infos<Param_Args...>& param_infos, const default_args<Default_Args...>& def_args)
  226. {
  227. }
  228. };
  229. /////////////////////////////////////////////////////////////////////////////////////////
  230. template<typename...Default_Args, typename...Param_Args>
  231. static RTTR_INLINE void store_default_args_in_param_infos(parameter_infos<Param_Args...>& param_infos, const default_args<Default_Args...>& def_args)
  232. {
  233. static_assert((sizeof...(Default_Args) <= sizeof...(Param_Args)), "Invalid size of default arguments!");
  234. using param_idx_seq = typename erase_sequence_till<make_index_sequence<sizeof...(Param_Args)>, sizeof...(Param_Args) - sizeof...(Default_Args)>::type;
  235. store_default_args_helper<make_index_sequence<sizeof...(Default_Args)>, param_idx_seq>::perform(param_infos, def_args);
  236. }
  237. /////////////////////////////////////////////////////////////////////////////////////////
  238. } // end namespace detail
  239. } // end namespace rttr
  240. #endif // RTTR_PARAMETER_INFOS_H_