You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

180 line
6.2 KiB

  1. #pragma once
  2. #include <cppmp/traits/lambda_traits.h>
  3. #include "setter.h"
  4. namespace cppmp
  5. {
  6. namespace __impl
  7. {
  8. /* setter_builder - default */
  9. template<typename X, typename>
  10. struct setter_builder
  11. {
  12. using is_default = cppmp::true_t;
  13. template<typename... T_args>
  14. static constexpr decltype(auto) apply(T_args&&...)
  15. { static_assert(sizeof...(T_args) == -1, "Invalid parameters for make_setter(...)!"); }
  16. };
  17. /* setter_builder - redirect existing setter */
  18. template<typename T_setter>
  19. struct setter_builder<
  20. list<T_setter>,
  21. enable_if_t<is_setter<decay_t<T_setter>>::value
  22. >>
  23. {
  24. static constexpr decltype(auto) apply(T_setter&& setter)
  25. { return std::forward<T_setter>(setter); }
  26. };
  27. /* setter_builder - member variable */
  28. template<typename T_object, typename T_value>
  29. struct setter_builder<
  30. list<T_value T_object::*>,
  31. void>
  32. {
  33. struct setter_member_var
  34. : public tag_setter
  35. , public tag_setter_member_var
  36. {
  37. using object_type = T_object;
  38. using value_type = T_value;
  39. using member_type = value_type object_type::*;
  40. member_type member;
  41. inline setter_member_var(member_type p_member)
  42. : member(p_member)
  43. { }
  44. inline setter_member_var(setter_member_var&&) = default;
  45. inline setter_member_var(const setter_member_var&) = default;
  46. inline setter_member_var& operator = (setter_member_var&&) = default;
  47. inline setter_member_var& operator = (const setter_member_var&) = default;
  48. template<typename X_object, typename X_value>
  49. constexpr void operator()(X_object&& obj, X_value&& value) const
  50. { std::forward<X_object>(obj).*member = value; }
  51. };
  52. using object_type = T_object;
  53. using value_type = T_value;
  54. using member_type = value_type object_type::*;
  55. static constexpr decltype(auto) apply(member_type&& setter)
  56. { return setter_member_var(std::forward<member_type>(setter)); }
  57. };
  58. /* setter_builder - member function */
  59. template<typename T_object, typename T_value, typename T_member>
  60. struct setter_builder_member_func
  61. {
  62. struct setter_member_func
  63. : public tag_setter
  64. , public tag_setter_member_func
  65. {
  66. using object_type = T_object;
  67. using value_type = T_value;
  68. using member_type = T_member;
  69. member_type member;
  70. inline setter_member_func(member_type p_member)
  71. : member(p_member)
  72. { }
  73. inline setter_member_func(setter_member_func&&) = default;
  74. inline setter_member_func(const setter_member_func&) = default;
  75. inline setter_member_func& operator = (setter_member_func&&) = default;
  76. inline setter_member_func& operator = (const setter_member_func&) = default;
  77. template<typename X_object, typename X_value>
  78. constexpr void operator()(X_object&& obj, X_value&& value) const
  79. { (std::forward<X_object>(obj).*member)(std::forward<X_value>(value)); }
  80. };
  81. using object_type = T_object;
  82. using value_type = T_value;
  83. using member_type = T_member;
  84. static constexpr decltype(auto) apply(member_type&& setter)
  85. { return setter_member_func(std::forward<member_type>(setter)); }
  86. };
  87. template<typename T_object, typename T_value>
  88. struct setter_builder<
  89. list<void (T_object::*)(T_value)>,
  90. void>
  91. : public setter_builder_member_func<T_object, T_value, void (T_object::*)(T_value)>
  92. { };
  93. template<typename T_object, typename T_value>
  94. struct setter_builder<
  95. list<void (T_object::*)(T_value) const>,
  96. void>
  97. : public setter_builder_member_func<const T_object, T_value, void (T_object::*)(T_value) const>
  98. { };
  99. /* setter_builder - lambda/static */
  100. template<typename T_lambda>
  101. struct setter_builder<
  102. list<T_lambda>,
  103. enable_if_t<
  104. is_valid<lambda_traits<decay_t<T_lambda>>>::value
  105. && lambda_traits<decay_t<T_lambda>>::argument_count_v == 2>>
  106. {
  107. struct setter_lambda
  108. : public tag_setter
  109. , public tag_setter_lambda
  110. {
  111. using lambda_type = T_lambda;
  112. using lambda_traits_type = lambda_traits<lambda_type>;
  113. using object_type = typename lambda_traits_type::template argument_t<0>;
  114. using value_type = typename lambda_traits_type::template argument_t<1>;
  115. lambda_type lambda;
  116. inline cppmp_constexpr_lambda setter_lambda(lambda_type&& p_lambda)
  117. : lambda(std::forward<lambda_type>(p_lambda))
  118. { }
  119. inline cppmp_constexpr_lambda setter_lambda(setter_lambda&&) = default;
  120. inline cppmp_constexpr_lambda setter_lambda(const setter_lambda&) = default;
  121. inline cppmp_constexpr_lambda setter_lambda& operator = (setter_lambda&&) = default;
  122. inline cppmp_constexpr_lambda setter_lambda& operator = (const setter_lambda&) = default;
  123. template<typename X_object, typename X_value>
  124. constexpr void operator()(X_object&& obj, X_value&& value) const
  125. { lambda(std::forward<X_object>(obj), std::forward<X_value>(value)); }
  126. };
  127. using lambda_type = T_lambda;
  128. static constexpr decltype(auto) apply(lambda_type&& lambda)
  129. { return setter_lambda(std::forward<lambda_type>(lambda)); }
  130. };
  131. }
  132. /* is_setter */
  133. template<typename T>
  134. struct is_setter
  135. : public is_base_of<tag_setter, T>
  136. { };
  137. }