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.

268 rader
7.2 KiB

  1. #pragma once
  2. #include <utility>
  3. #include <cpputils/mp/misc/make.h>
  4. #include <cpputils/mp/core/const.h>
  5. #include <cpputils/mp/core/modifier.h>
  6. #include <cpputils/mp/operations/hash.fwd.h>
  7. #include <cpputils/mp/intern/operators_comparable.h>
  8. namespace utl {
  9. namespace mp {
  10. namespace __impl /* forward declaration */
  11. {
  12. template<typename T>
  13. struct type_impl;
  14. struct decl_type_t
  15. {
  16. template<typename T>
  17. constexpr auto operator()(T&& t) const;
  18. };
  19. struct type_id_t
  20. {
  21. template <typename T>
  22. constexpr auto operator()(T&&) const;
  23. };
  24. struct size_of_t
  25. {
  26. template <typename T>
  27. constexpr auto operator()(T&&) const;
  28. };
  29. struct align_of_t
  30. {
  31. template <typename T>
  32. constexpr auto operator()(T&&) const;
  33. };
  34. struct is_valid_type_t
  35. {
  36. template <typename F>
  37. constexpr auto operator()(F&&) const;
  38. template <typename F, typename ...Args>
  39. constexpr auto operator()(F&&, Args&&...) const;
  40. };
  41. template <template <typename ...> class F>
  42. struct tmplt_t;
  43. template <template <typename ...> class F>
  44. struct metafunction_t;
  45. template <typename F>
  46. struct metafunction_class_t
  47. : metafunction_t<F::template apply>
  48. { };
  49. template <typename F>
  50. struct integral_t;
  51. struct make_integral_t
  52. {
  53. template <typename F>
  54. constexpr integral_t<F> operator()(F const&) const
  55. { return { }; }
  56. };
  57. }
  58. struct tag_type { };
  59. template<typename T>
  60. using type = typename __impl::type_impl<T>::type;
  61. template<typename T>
  62. constexpr type<T> type_c { };
  63. constexpr auto make_mp_type = make<tag_type>;
  64. constexpr __impl::decl_type_t decl_type { };
  65. constexpr __impl::type_id_t type_id { };
  66. constexpr __impl::size_of_t size_of { };
  67. constexpr __impl::align_of_t align_of { };
  68. constexpr __impl::is_valid_type_t is_valid_type { };
  69. template <template <typename ...> class F>
  70. constexpr __impl::tmplt_t<F> tmplt { };
  71. template <template <typename ...> class F>
  72. constexpr __impl::metafunction_t<F> metafunction { };
  73. template <typename F>
  74. constexpr __impl::metafunction_class_t<F> metafunction_class { };
  75. constexpr __impl::make_integral_t integral { };
  76. template <template <typename ...> class F>
  77. constexpr auto trait = integral(metafunction<F>);
  78. namespace __impl /* implementation */
  79. {
  80. /* basic_type */
  81. template<typename T>
  82. struct basic_type
  83. {
  84. using tag = tag_type;
  85. using type = T;
  86. constexpr auto operator+() const
  87. { return *this; }
  88. };
  89. /* type */
  90. template<typename T>
  91. struct type_impl
  92. {
  93. struct type : basic_type<T>
  94. { };
  95. };
  96. /* decl_type */
  97. template <typename T, typename = tag_type>
  98. struct decltype_helper
  99. { using type = remove_ref<T>; };
  100. template <typename T>
  101. struct decltype_helper<T, tag_of<T>>
  102. { using type = typename remove_ref<T>::type; };
  103. template<typename T>
  104. constexpr auto decl_type_t::operator()(T&& t) const
  105. { return type_c<typename decltype_helper<T>::type>; }
  106. /* type_id */
  107. template <typename T, typename = tag_type>
  108. struct typeid_helper
  109. { using type = clean_type<T>; };
  110. template <typename T>
  111. struct typeid_helper<T, tag_of<T>>
  112. { using type = typename remove_ref<T>::type; };
  113. template <typename T>
  114. constexpr auto type_id_t::operator()(T&&) const
  115. { return type_c<typename typeid_helper<T>::type>; }
  116. /* make */
  117. template <>
  118. struct make_impl<tag_type>
  119. {
  120. template <typename T>
  121. static constexpr auto apply(T&& t)
  122. { return type_id(std::forward<T>(t)); }
  123. };
  124. /* size_of */
  125. template <typename T>
  126. constexpr auto size_of_t::operator()(T&&) const
  127. { return c_size_t<sizeof(typename decltype_helper<T>::type)> { }; }
  128. /* align_of */
  129. template <typename T>
  130. constexpr auto align_of_t::operator()(T&&) const
  131. { return c_size_t<alignof(typename decltype_helper<T>::type)> { }; }
  132. /* is_valid_type */
  133. template<typename F, typename... Args, typename = decltype(std::declval<F&&>()(std::declval<Args&&>()...))>
  134. constexpr auto is_valid_type_impl(int)
  135. { return c_true; }
  136. template<typename F, typename... Args>
  137. constexpr auto is_valid_type_impl(...)
  138. { return c_false; }
  139. template<typename F>
  140. struct is_valid_type_helper
  141. {
  142. template<typename... Args>
  143. constexpr auto operator()(Args&&...) const
  144. { return is_valid_type_impl<F, Args&&...>(int { }); }
  145. };
  146. template <typename F>
  147. constexpr auto is_valid_type_t::operator()(F&&) const
  148. { return is_valid_type_helper<F&&> { }; }
  149. template <typename F, typename ...Args>
  150. constexpr auto is_valid_type_t::operator()(F&&, Args&&...) const
  151. { return is_valid_type_impl<F&&, Args&&...>(int { }); }
  152. /* tmplt */
  153. template <template <typename ...> class F>
  154. struct tmplt_t
  155. {
  156. template<typename... T>
  157. struct apply
  158. { using type = F<T...>; };
  159. template<typename... T>
  160. constexpr auto operator()(const T&...) const
  161. { return type<F<typename T::type...>> { }; }
  162. };
  163. /* metafunction */
  164. template <template <typename ...> class F>
  165. struct metafunction_t
  166. {
  167. template<typename... T>
  168. using apply = F<T...>;
  169. template<typename... T>
  170. constexpr type<typename F<typename T::type...>::type> operator()(const T&...) const
  171. { return { }; }
  172. };
  173. /* integral */
  174. template <typename F>
  175. struct integral_t
  176. {
  177. template<typename... T>
  178. constexpr auto operator()(const T& ...) const
  179. {
  180. using result_type = typename F::template apply<typename T::type...>::type;
  181. return result_type { };
  182. }
  183. };
  184. /* equal */
  185. template <>
  186. struct equal_impl<tag_type, tag_type>
  187. {
  188. template <typename T, typename U>
  189. static constexpr auto apply(const basic_type<T>&, const basic_type<U>&)
  190. { return c_false; }
  191. template <typename T>
  192. static constexpr auto apply(const basic_type<T>&, const basic_type<T>&)
  193. { return c_true; }
  194. };
  195. /* hash */
  196. template<>
  197. struct hash_impl<tag_type>
  198. {
  199. template <typename T>
  200. static constexpr T apply(const T& t)
  201. { return t; }
  202. };
  203. }
  204. namespace intern {
  205. template<>
  206. struct operators_comparable<tag_type>
  207. { static constexpr bool value = true; };
  208. }
  209. }
  210. }