default_arguments.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  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_DEFAULT_ARGUMENTS_H_
  28. #define RTTR_DEFAULT_ARGUMENTS_H_
  29. #include "rttr/detail/base/core_prerequisites.h"
  30. #include "rttr/detail/misc/misc_type_traits.h"
  31. #include "rttr/detail/misc/argument_extractor.h"
  32. #include "rttr/detail/misc/function_traits.h"
  33. #include <tuple>
  34. namespace rttr
  35. {
  36. namespace detail
  37. {
  38. /*!
  39. * This class holds the data for the default arguments.
  40. */
  41. template<typename...T>
  42. struct default_args
  43. {
  44. default_args() {}
  45. default_args(T&&... args) : m_args(std::forward<T>(args)...) {}
  46. std::tuple<T...> m_args;
  47. };
  48. template<>
  49. struct default_args<>
  50. {
  51. default_args() {}
  52. std::tuple<> m_args;
  53. };
  54. struct constructor_type {};
  55. struct function_type {};
  56. /////////////////////////////////////////////////////////////////////////////////////////
  57. // a helper class to store two default list, the user provided, with std::nullptr_t
  58. // and the function signature:
  59. // e.g. default_args<int, bool*> , default_args<int, nullptr>
  60. // this is needed for the get_default_args() function, to copy the values from the std::nullptr_t list
  61. // to the function signature list
  62. template<typename T1, typename T2>
  63. struct default_list
  64. {
  65. using default_types_func = T1;
  66. using default_types_provided = T2;
  67. };
  68. // short cut for an empty list
  69. using empty_defaults = default_list<default_args<>, default_args<>>;
  70. /////////////////////////////////////////////////////////////////////////////////////////
  71. // This type trait will check whether a signature (given via \p Arg_list) match the \o Default_Arg_List types.
  72. // It will check the signature recursively, beginning with the complete signature,
  73. // then removing the first argument and check against Default_Arg_List, then removing the second...
  74. template<typename Arg_list, typename Default_Arg_List>
  75. struct find_default_args_impl;
  76. template<typename Default_Arg_List, typename T, typename...TArgs>
  77. struct find_default_args_impl<type_list<T, TArgs...>, Default_Arg_List>
  78. {
  79. template<typename Tx>
  80. using decay_type = remove_cv_t<remove_reference_t< Tx >>;
  81. using func_args = default_args< decay_type< T>,
  82. decay_type< TArgs>...
  83. >;
  84. using type = conditional_t< is_same_nullptr<func_args, Default_Arg_List>::value,
  85. default_list<func_args, Default_Arg_List>,
  86. typename find_default_args_impl<type_list<TArgs...>, Default_Arg_List >::type
  87. >;
  88. };
  89. template<typename Default_Arg_List>
  90. struct find_default_args_impl<type_list<>, Default_Arg_List>
  91. {
  92. using type = default_list<default_args<>, default_args<>>;
  93. };
  94. /////////////////////////////////////////////////////////////////////////////////////////
  95. /*!
  96. * This helper struct is needed to call `find_default_args_t` with a function signature,
  97. * or a constructor signature (a list of arguments), i.e. I have only one interface to invoke.
  98. *
  99. * This avoid code distinction in `has_default_types`or `get_default_args`.
  100. */
  101. template<typename Default_Arg_List, typename T, typename Acc_Type, typename Enable = void>
  102. struct find_default_args_helper;
  103. // is function
  104. template<typename Default_Arg_List, typename T, typename Acc_Type>
  105. struct find_default_args_helper<Default_Arg_List, type_list<T>, Acc_Type, enable_if_t< std::is_same<Acc_Type, function_type>::value >>
  106. : find_default_args_impl< as_type_list_t< typename function_traits<T>::arg_types >, Default_Arg_List>
  107. {
  108. };
  109. // is ctor with one argument
  110. template<typename Default_Arg_List, typename T>
  111. struct find_default_args_helper<Default_Arg_List, type_list<T>, constructor_type, enable_if_t< is_one_argument<T>::value >>
  112. : find_default_args_impl<type_list<T>, Default_Arg_List>
  113. {
  114. };
  115. // is ctor with zero or more then one argument
  116. template<typename Default_Arg_List, typename...TArgs>
  117. struct find_default_args_helper<Default_Arg_List, type_list<TArgs...>, constructor_type, enable_if_t< !is_one_argument<TArgs...>::value >>
  118. : find_default_args_impl<type_list<TArgs...>, Default_Arg_List>
  119. {
  120. };
  121. /*!
  122. * This type traits will check whether it is possible to call
  123. * a function type or a list of argument types (e.g. constructor arguments)
  124. * depending on a list of default argument types, \p Default_Arg_List.
  125. * When it is possible \p Default_Arg_List will be returned as type;
  126. * Otherwise an empty 'default_args<>' will be returned
  127. *
  128. * e.g.:
  129. * ctor_list => <bool, int, double>; Default_Arg_List => default_args<bool, int, double> will return: default_args<bool, int, double>
  130. * ctor_list => <bool, int, double>; Default_Arg_List => default_args<int, double> will return: default_args<int, double>
  131. * ctor_list => <bool, int, double>; Default_Arg_List => default_args<double> will return: default_args<double>
  132. * ctor_list => <bool, int, double>; Default_Arg_List => default_args<int> will return: default_args<> (cannot be called; right most argument is missing)
  133. */
  134. template<typename Default_Arg_List, typename Acc_Args, typename Acc_Type>
  135. using find_default_args_t = typename find_default_args_helper<Default_Arg_List, Acc_Args, Acc_Type>::type;
  136. /////////////////////////////////////////////////////////////////////////////////////////
  137. template<typename T>
  138. struct is_def_type : std::false_type { };
  139. template<typename... TArgs>
  140. struct is_def_type<default_args<TArgs...> > : std::true_type { };
  141. /////////////////////////////////////////////////////////////////////////////////////////
  142. template<typename T>
  143. struct get_default_args_impl;
  144. template<typename T, typename...TArgs>
  145. struct get_default_args_impl<type_list<T, TArgs...>>
  146. {
  147. using type = conditional_t< is_def_type<T>::value,
  148. T,
  149. typename get_default_args_impl<type_list<TArgs...>>::type
  150. >;
  151. };
  152. template<>
  153. struct get_default_args_impl<type_list<>>
  154. {
  155. using type = default_args<>;
  156. };
  157. //! This type trait will return the first type which matches the template type `default_args<T...>`
  158. template<typename...TArgs>
  159. using get_default_args_t = typename get_default_args_impl< type_list< TArgs... > >::type;
  160. /////////////////////////////////////////////////////////////////////////////////////////
  161. /////////////////////////////////////////////////////////////////////////////////////////
  162. /////////////////////////////////////////////////////////////////////////////////////////
  163. /*!
  164. * Evaluates to 'std::true_type' when the given arguments contains one 'def_args<T...>' argument;
  165. * Otherwise to 'std::false_type'
  166. */
  167. template<typename...Args>
  168. using has_default_args = std::integral_constant<bool, !std::is_same<get_default_args_t<Args...>, default_args<>>::value>;
  169. template<typename T1, typename T2, typename Acc_Type>
  170. struct has_default_types;
  171. /*!
  172. * Evaluates to 'std::true_type' when the given arguments contains one valid 'def_args<T...>' argument,
  173. * that can be used to invoke the signature \p Acc_Args;
  174. * Otherwise to 'std::false_type'
  175. */
  176. template<typename Acc_Args, typename Acc_Type, typename... TArgs>
  177. struct has_default_types<Acc_Args, type_list<TArgs...>, Acc_Type>
  178. : std::integral_constant<bool, !std::is_same<find_default_args_t<get_default_args_t<TArgs...>, Acc_Args, Acc_Type>, empty_defaults>::value>
  179. {
  180. };
  181. /////////////////////////////////////////////////////////////////////////////////////////
  182. template<typename Acc_Args, typename Acc_Type, typename... TArgs>
  183. using default_types_t = find_default_args_t<get_default_args_t<TArgs...>, Acc_Args, Acc_Type>;
  184. /////////////////////////////////////////////////////////////////////////////////////////
  185. /////////////////////////////////////////////////////////////////////////////////////////
  186. /////////////////////////////////////////////////////////////////////////////////////////
  187. // returns the number of types 'default_args<T...>' provided in the given list of arguments TArgs...
  188. template<typename...TArgs>
  189. using count_default_args = count_if<is_def_type, raw_type_t<TArgs>... >;
  190. /////////////////////////////////////////////////////////////////////////////////////////
  191. /////////////////////////////////////////////////////////////////////////////////////////
  192. /////////////////////////////////////////////////////////////////////////////////////////
  193. template<typename Acc_Args, typename Acc_Type, typename... Args, typename Default_Type = find_default_args_t<get_default_args_t<Args...>, Acc_Args, Acc_Type> >
  194. static RTTR_INLINE
  195. enable_if_t< std::is_same<Default_Type, empty_defaults>::value, typename Default_Type::default_types_func>
  196. get_default_args(Args&&... arg)
  197. {
  198. return default_args<>(); // no default arguments provided
  199. }
  200. /////////////////////////////////////////////////////////////////////////////////////////
  201. template<typename Acc_Args, typename Acc_Type, typename... Args, typename Default_Type = find_default_args_t<get_default_args_t<Args...>, Acc_Args, Acc_Type> >
  202. static RTTR_INLINE
  203. enable_if_t< !std::is_same<Default_Type, empty_defaults>::value, typename Default_Type::default_types_func>
  204. get_default_args(Args&&... arg)
  205. {
  206. // default arguments are provided, extract them
  207. auto result = forward_to_array<typename Default_Type::default_types_provided>(std::forward<Args>(arg)...);
  208. // because we knew there is exactly one detail::default_argument,
  209. // we can extract it without worry to check
  210. typename Default_Type::default_types_func ret;
  211. ret.m_args = std::move(result[0].m_args);
  212. return ret;
  213. }
  214. /////////////////////////////////////////////////////////////////////////////////////////
  215. } // end namespace detail
  216. } // end namespace rttr
  217. #endif // RTTR_DEFAULT_ARGUMENTS_H_