invoke_with_defaults.h 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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_INVOKE_WITH_DEFAULTS_H_
  28. #define RTTR_INVOKE_WITH_DEFAULTS_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 <type_traits>
  34. namespace rttr
  35. {
  36. namespace detail
  37. {
  38. template<typename Ctor_Args, typename List1, typename List2>
  39. struct are_args_and_defaults_in_valid_range;
  40. template<typename... Ctor_Args, typename... TArgs, typename... Default_Args>
  41. struct are_args_and_defaults_in_valid_range<type_list<Ctor_Args...>, type_list<TArgs...>, type_list<Default_Args...>>
  42. : std::integral_constant<bool, (sizeof...(TArgs) <= sizeof...(Ctor_Args)) && ( sizeof...(TArgs) + sizeof...(Default_Args) >= sizeof...(Ctor_Args)) >
  43. {
  44. };
  45. template<typename F, typename...TArgs, typename...Default_Args>
  46. struct are_args_and_defaults_in_valid_range<F, type_list<TArgs...>, type_list<Default_Args...>>
  47. : are_args_and_defaults_in_valid_range<as_type_list_t<typename function_traits<F>::arg_types>, type_list<TArgs...>, type_list<Default_Args...>>
  48. {
  49. };
  50. /////////////////////////////////////////////////////////////////////////////////////////
  51. /*!
  52. * A helper class to invoke functions objects with default arguments,
  53. * via static method `Invoker_Class::invoke`
  54. */
  55. template<typename Invoker_Class, typename F>
  56. struct invoke_defaults_helper
  57. {
  58. private:
  59. template<std::size_t... Def_Idx, typename... Def_Types, typename... TArgs>
  60. static RTTR_INLINE variant
  61. invoke_with_defaults_helper(const F& func_ptr, const instance& obj, index_sequence<Def_Idx...>,
  62. const std::tuple<Def_Types...>& def_args, const TArgs&...args)
  63. {
  64. return Invoker_Class::invoke(func_ptr, obj, args..., argument(std::get<Def_Idx>(def_args))...);
  65. }
  66. public:
  67. template<typename... Def_Types, typename... TArgs>
  68. static RTTR_INLINE
  69. enable_if_t< are_args_and_defaults_in_valid_range<F, type_list<TArgs...>, type_list<Def_Types...>>::value, variant>
  70. invoke(const F& func_ptr, const instance& obj, const std::tuple<Def_Types...>& def_args, const TArgs&...args)
  71. {
  72. static RTTR_CONSTEXPR_OR_CONST std::size_t arg_count = function_traits<F>::arg_count;
  73. // here we calculate the integer sequence for retrieving the data from the tuple,
  74. // this depends on the number of arguments provided by the caller
  75. static RTTR_CONSTEXPR_OR_CONST std::size_t start_index = sizeof...(TArgs) + sizeof...(Def_Types) - arg_count;
  76. using idx_seq = typename erase_sequence_till<index_sequence_for<Def_Types...>, start_index>::type;
  77. return invoke_with_defaults_helper(func_ptr, obj, idx_seq(), def_args, args...);
  78. }
  79. /////////////////////////////////////////////////////////////////////////////////////
  80. template<typename... Def_Types, typename... TArgs>
  81. static RTTR_INLINE
  82. enable_if_t< !are_args_and_defaults_in_valid_range<F, type_list<TArgs...>, type_list<Def_Types...>>::value, variant>
  83. invoke(const F& func_ptr, const instance& obj, const std::tuple<Def_Types...>& def_args, const TArgs&...args)
  84. {
  85. return variant();
  86. }
  87. };
  88. /////////////////////////////////////////////////////////////////////////////////////////
  89. /*!
  90. * A helper class to invoke a constructor signature with default arguments,
  91. * via static method `Invoker_Class::invoke`
  92. */
  93. template<typename Invoker_Class, typename... Ctor_Args>
  94. struct invoke_defaults_helper<Invoker_Class, type_list<Ctor_Args...>>
  95. {
  96. private:
  97. template<std::size_t... Def_Idx, typename... Def_Types, typename... TArgs>
  98. static RTTR_INLINE variant
  99. invoke_with_defaults_extract(index_sequence<Def_Idx...>, const std::tuple<Def_Types...>& def_args, const TArgs&...args)
  100. {
  101. return Invoker_Class::invoke(args..., argument(std::get<Def_Idx>(def_args))...);
  102. }
  103. public:
  104. template<typename... Def_Types, typename... TArgs>
  105. static RTTR_INLINE
  106. enable_if_t< are_args_and_defaults_in_valid_range<type_list<Ctor_Args...>, type_list<TArgs...>, type_list<Def_Types...>>::value, variant>
  107. invoke(const std::tuple<Def_Types...>& def_args, const TArgs&...args)
  108. {
  109. static RTTR_CONSTEXPR_OR_CONST std::size_t arg_count = sizeof...(Ctor_Args);
  110. // here we calculate the integer sequence for retrieving the data from the tuple,
  111. // this depends on the number of arguments provided by the caller
  112. static RTTR_CONSTEXPR_OR_CONST std::size_t start_index = sizeof...(TArgs) + sizeof...(Def_Types) - arg_count;
  113. using idx_seq = typename erase_sequence_till<index_sequence_for<Def_Types...>, start_index>::type;
  114. return invoke_with_defaults_extract(idx_seq(), def_args, args...);
  115. }
  116. /////////////////////////////////////////////////////////////////////////////////////
  117. template<typename... Def_Types, typename... TArgs>
  118. static RTTR_INLINE
  119. enable_if_t< !are_args_and_defaults_in_valid_range<type_list<Ctor_Args...>, type_list<TArgs...>, type_list<Def_Types...>>::value, variant>
  120. invoke(const std::tuple<Def_Types...>& def_args, const TArgs&...args)
  121. {
  122. return variant();
  123. }
  124. };
  125. /////////////////////////////////////////////////////////////////////////////////////////
  126. template<typename Invoker_Class, typename Arg_Indexer>
  127. struct invoke_variadic_helper;
  128. /*!
  129. * Generic class to call the static method 'Invoker_Class::invoke',
  130. * with the correct argument list 'size()'; this can only be decided at runtime.
  131. */
  132. template<typename Invoker_Class, std::size_t... Arg_Idx>
  133. struct invoke_variadic_helper<Invoker_Class, index_sequence<Arg_Idx...>>
  134. {
  135. template<typename... Args>
  136. static RTTR_INLINE variant invoke(std::vector<argument>& arg_list, Args&&...args)
  137. {
  138. static RTTR_CONSTEXPR_OR_CONST std::size_t Arg_Count = sizeof...(Arg_Idx);
  139. if (arg_list.size() == Arg_Count)
  140. return Invoker_Class::invoke(args..., arg_list[Arg_Idx]...);
  141. else
  142. return invoke_variadic_helper<Invoker_Class, make_index_sequence<Arg_Count - 1>>::invoke(arg_list, args...);
  143. }
  144. };
  145. template<typename Invoker_Class>
  146. struct invoke_variadic_helper<Invoker_Class, index_sequence<>>
  147. {
  148. template<typename...Args>
  149. static RTTR_INLINE variant invoke(std::vector<argument>& arg_list, Args&&...args)
  150. {
  151. return Invoker_Class::invoke(args...);
  152. }
  153. };
  154. /////////////////////////////////////////////////////////////////////////////////////////
  155. } // end namespace detail
  156. } // end namespace rttr
  157. #endif // RTTR_DEFAULT_ARGUMENTS_H_