Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 

237 rader
8.3 KiB

  1. #pragma once
  2. #include <cppmp/core/modifier.h>
  3. #include <cppmp/traits/lambda_traits.h>
  4. #include "getter.h"
  5. namespace cppmp
  6. {
  7. namespace __impl
  8. {
  9. /* getter_builder - default */
  10. template<typename X, typename>
  11. struct getter_builder
  12. {
  13. using is_default = cppmp::true_t;
  14. template<typename... T_args>
  15. static constexpr decltype(auto) apply(T_args&&...)
  16. { static_assert(sizeof...(T_args) == -1, "Invalid parameters for make_getter(...)!"); }
  17. };
  18. /* getter_builder - redirect existing getter */
  19. template<typename T_getter>
  20. struct getter_builder<
  21. list<T_getter>,
  22. enable_if_t<is_getter<decay_t<T_getter>>::value
  23. >>
  24. {
  25. static constexpr decltype(auto) apply(T_getter&& getter)
  26. { return std::forward<T_getter>(getter); }
  27. };
  28. /* getter_builder - member variable */
  29. template<typename T_object, typename T_value>
  30. struct getter_builder<
  31. list<T_value T_object::*>,
  32. enable_if_t<
  33. !is_valid<lambda_traits<T_value T_object::*>>::value
  34. >
  35. >
  36. {
  37. struct getter_member_var
  38. : public tag_getter
  39. , public tag_getter_member_var
  40. {
  41. using object_type = T_object;
  42. using value_type = T_value;
  43. using member_type = value_type object_type::*;
  44. member_type member;
  45. inline getter_member_var(member_type p_member)
  46. : member(p_member)
  47. { }
  48. inline getter_member_var(getter_member_var&&) = default;
  49. inline getter_member_var(const getter_member_var&) = default;
  50. inline getter_member_var& operator = (getter_member_var&&) = default;
  51. inline getter_member_var& operator = (const getter_member_var&) = default;
  52. template<typename X_object>
  53. constexpr decltype(auto) operator()(X_object&& obj) const
  54. { return std::forward<X_object>(obj).*member; }
  55. };
  56. using object_type = T_object;
  57. using value_type = T_value;
  58. using member_type = value_type object_type::*;
  59. static constexpr decltype(auto) apply(member_type&& getter)
  60. { return getter_member_var(std::forward<member_type>(getter)); }
  61. };
  62. /* getter_builder - member function */
  63. template<typename T_object, typename T_value, typename T_member>
  64. struct getter_builder_member_func
  65. {
  66. struct getter_member_func
  67. : public tag_getter
  68. , public tag_getter_member_func
  69. {
  70. using object_type = T_object;
  71. using value_type = T_value;
  72. using member_type = T_member;
  73. member_type member;
  74. inline getter_member_func(member_type p_member)
  75. : member(p_member)
  76. { }
  77. inline getter_member_func(getter_member_func&&) = default;
  78. inline getter_member_func(const getter_member_func&) = default;
  79. inline getter_member_func& operator = (getter_member_func&&) = default;
  80. inline getter_member_func& operator = (const getter_member_func&) = default;
  81. template<typename X_object>
  82. constexpr decltype(auto) operator()(X_object&& obj) const
  83. { return (std::forward<X_object>(obj).*member)(); }
  84. };
  85. using object_type = T_object;
  86. using value_type = T_value;
  87. using member_type = T_member;
  88. static constexpr decltype(auto) apply(member_type&& getter)
  89. { return getter_member_func(std::forward<member_type>(getter)); }
  90. };
  91. template<typename T_object, typename T_value>
  92. struct getter_builder<
  93. list<T_value (T_object::*)()>,
  94. void>
  95. : public getter_builder_member_func<T_object, T_value, T_value (T_object::*)()>
  96. { };
  97. template<typename T_object, typename T_value>
  98. struct getter_builder<
  99. list<T_value (T_object::*)() const>,
  100. void>
  101. : public getter_builder_member_func<const T_object, T_value, T_value (T_object::*)() const>
  102. { };
  103. /* getter_builder - lambda/static */
  104. template<typename T_lambda>
  105. struct getter_builder<
  106. list<T_lambda>,
  107. enable_if_t<
  108. is_valid<lambda_traits<decay_t<T_lambda>>>::value
  109. && lambda_traits<decay_t<T_lambda>>::argument_count_v == 1
  110. && !is_void<typename lambda_traits<decay_t<T_lambda>>::return_type>::value
  111. >
  112. >
  113. {
  114. struct getter_lambda
  115. : public tag_getter
  116. , public tag_getter_lambda
  117. {
  118. using lambda_type = T_lambda;
  119. using lambda_traits_type = lambda_traits<lambda_type>;
  120. using object_type = typename lambda_traits_type::template argument_t<0>;
  121. using value_type = typename lambda_traits_type::return_type;
  122. lambda_type lambda;
  123. inline getter_lambda(lambda_type&& p_lambda)
  124. : lambda(std::forward<lambda_type>(p_lambda))
  125. { }
  126. inline getter_lambda(getter_lambda&&) = default;
  127. inline getter_lambda(const getter_lambda&) = default;
  128. inline getter_lambda& operator = (getter_lambda&&) = default;
  129. inline getter_lambda& operator = (const getter_lambda&) = default;
  130. template<typename X_object>
  131. constexpr decltype(auto) operator()(X_object&& obj) const
  132. { return lambda(std::forward<X_object>(obj)); }
  133. };
  134. using lambda_type = T_lambda;
  135. static constexpr decltype(auto) apply(lambda_type&& lambda)
  136. { return getter_lambda(std::forward<lambda_type>(lambda)); }
  137. };
  138. /* getter_builder - chain */
  139. template<typename T_first, typename T_second, typename... T_rest>
  140. struct getter_builder<
  141. list<T_first, T_second, T_rest...>,
  142. enable_if_t<
  143. is_valid<decltype(make_getter(std::declval<T_first>()))>::value
  144. && is_valid<decltype(make_getter(std::declval<T_second>(), std::declval<T_rest>()...))>::value
  145. >
  146. >
  147. {
  148. struct getter_chain
  149. : public tag_getter
  150. , public tag_getter_chain
  151. {
  152. using first_getter_type = decltype(make_getter(std::declval<T_first>()));
  153. using second_getter_type = decltype(make_getter(std::declval<T_second>(), std::declval<T_rest>()...));
  154. using object_type = typename first_getter_type::object_type;
  155. using value_type = typename second_getter_type::value_type;;
  156. first_getter_type first;
  157. second_getter_type second;
  158. inline getter_chain(
  159. first_getter_type&& p_first,
  160. second_getter_type&& p_second)
  161. : first (std::move(p_first))
  162. , second(std::move(p_second))
  163. { }
  164. inline getter_chain(getter_chain&&) = default;
  165. inline getter_chain(const getter_chain&) = default;
  166. inline getter_chain& operator = (getter_chain&&) = default;
  167. inline getter_chain& operator = (const getter_chain&) = default;
  168. template<typename X_object>
  169. constexpr decltype(auto) operator()(X_object&& obj) const
  170. { return second(first(std::forward<X_object>(obj))); }
  171. };
  172. template<typename X_first, typename... X_rest>
  173. static constexpr decltype(auto) apply(X_first&& first, X_rest&&... rest)
  174. {
  175. return getter_chain(
  176. make_getter(std::forward<X_first>(first)),
  177. make_getter(std::forward<X_rest>(rest)...));
  178. }
  179. };
  180. }
  181. /* is_getter */
  182. template<typename T>
  183. struct is_getter
  184. : public is_base_of<tag_getter, T>
  185. { };
  186. }