type.hpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /*!
  2. @file
  3. Defines `boost::hana::type` and related utilities.
  4. Copyright Louis Dionne 2013-2022
  5. Distributed under the Boost Software License, Version 1.0.
  6. (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
  7. */
  8. #ifndef BOOST_HANA_TYPE_HPP
  9. #define BOOST_HANA_TYPE_HPP
  10. #include <boost/hana/fwd/type.hpp>
  11. #include <boost/hana/bool.hpp>
  12. #include <boost/hana/config.hpp>
  13. #include <boost/hana/core/when.hpp>
  14. #include <boost/hana/detail/operators/adl.hpp>
  15. #include <boost/hana/detail/operators/comparable.hpp>
  16. #include <boost/hana/fwd/concept/metafunction.hpp>
  17. #include <boost/hana/fwd/core/make.hpp>
  18. #include <boost/hana/fwd/equal.hpp>
  19. #include <boost/hana/fwd/hash.hpp>
  20. #include <boost/hana/integral_constant.hpp>
  21. #include <type_traits>
  22. #include <utility>
  23. namespace boost { namespace hana {
  24. //////////////////////////////////////////////////////////////////////////
  25. // basic_type
  26. //////////////////////////////////////////////////////////////////////////
  27. //! @cond
  28. template <typename T>
  29. struct basic_type : detail::operators::adl<basic_type<T>> {
  30. using hana_tag = type_tag;
  31. using type = T;
  32. constexpr auto operator+() const { return *this; }
  33. };
  34. //! @endcond
  35. //////////////////////////////////////////////////////////////////////////
  36. // type
  37. //////////////////////////////////////////////////////////////////////////
  38. template <typename T>
  39. struct type_impl {
  40. struct _ : basic_type<T> { };
  41. };
  42. //////////////////////////////////////////////////////////////////////////
  43. // decltype_
  44. //////////////////////////////////////////////////////////////////////////
  45. namespace detail {
  46. template <typename T, typename = type_tag>
  47. struct decltype_t {
  48. using type = typename std::remove_reference<T>::type;
  49. };
  50. template <typename T>
  51. struct decltype_t<T, typename hana::tag_of<T>::type> {
  52. using type = typename std::remove_reference<T>::type::type;
  53. };
  54. }
  55. //! @cond
  56. template <typename T>
  57. constexpr auto decltype_t::operator()(T&&) const
  58. { return hana::type_c<typename detail::decltype_t<T>::type>; }
  59. //! @endcond
  60. //////////////////////////////////////////////////////////////////////////
  61. // typeid_
  62. //////////////////////////////////////////////////////////////////////////
  63. namespace detail {
  64. template <typename T, typename = type_tag>
  65. struct typeid_t {
  66. using type = typename std::remove_cv<
  67. typename std::remove_reference<T>::type
  68. >::type;
  69. };
  70. template <typename T>
  71. struct typeid_t<T, typename hana::tag_of<T>::type> {
  72. using type = typename std::remove_reference<T>::type::type;
  73. };
  74. }
  75. //! @cond
  76. template <typename T>
  77. constexpr auto typeid_t::operator()(T&&) const
  78. { return hana::type_c<typename detail::typeid_t<T>::type>; }
  79. //! @endcond
  80. //////////////////////////////////////////////////////////////////////////
  81. // make<type_tag>
  82. //////////////////////////////////////////////////////////////////////////
  83. template <>
  84. struct make_impl<type_tag> {
  85. template <typename T>
  86. static constexpr auto apply(T&& t)
  87. { return hana::typeid_(static_cast<T&&>(t)); }
  88. };
  89. //////////////////////////////////////////////////////////////////////////
  90. // sizeof_
  91. //////////////////////////////////////////////////////////////////////////
  92. //! @cond
  93. template <typename T>
  94. constexpr auto sizeof_t::operator()(T&&) const
  95. { return hana::size_c<sizeof(typename detail::decltype_t<T>::type)>; }
  96. //! @endcond
  97. //////////////////////////////////////////////////////////////////////////
  98. // alignof_
  99. //////////////////////////////////////////////////////////////////////////
  100. //! @cond
  101. template <typename T>
  102. constexpr auto alignof_t::operator()(T&&) const
  103. { return hana::size_c<alignof(typename detail::decltype_t<T>::type)>; }
  104. //! @endcond
  105. //////////////////////////////////////////////////////////////////////////
  106. // is_valid
  107. //////////////////////////////////////////////////////////////////////////
  108. namespace type_detail {
  109. template <typename F, typename ...Args, typename = decltype(
  110. std::declval<F&&>()(std::declval<Args&&>()...)
  111. )>
  112. constexpr auto is_valid_impl(int) { return hana::true_c; }
  113. template <typename F, typename ...Args>
  114. constexpr auto is_valid_impl(...) { return hana::false_c; }
  115. template <typename F>
  116. struct is_valid_fun {
  117. template <typename ...Args>
  118. constexpr auto operator()(Args&& ...) const
  119. { return is_valid_impl<F, Args&&...>(int{}); }
  120. };
  121. }
  122. //! @cond
  123. template <typename F>
  124. constexpr auto is_valid_t::operator()(F&&) const
  125. { return type_detail::is_valid_fun<F&&>{}; }
  126. template <typename F, typename ...Args>
  127. constexpr auto is_valid_t::operator()(F&&, Args&& ...) const
  128. { return type_detail::is_valid_impl<F&&, Args&&...>(int{}); }
  129. //! @endcond
  130. //////////////////////////////////////////////////////////////////////////
  131. // template_
  132. //////////////////////////////////////////////////////////////////////////
  133. // Note: We have to use the very complicated trick below instead of just
  134. // mentionning `F<T...>` in a SFINAE-able context because of CWG 1430
  135. // (http://www.open-std.org/Jtc1/sc22/wg21/docs/cwg_active.html#1430).
  136. namespace template_detail {
  137. template <typename ...T> struct args;
  138. template <typename ...> using always_void = void;
  139. template <template <typename ...> class F, typename Args, typename = void>
  140. struct specialization_is_valid
  141. : std::false_type
  142. { };
  143. template <template <typename ...> class F, typename ...T>
  144. struct specialization_is_valid<F, args<T...>, always_void<F<T...>>>
  145. : std::true_type
  146. { };
  147. } // end namespace detail
  148. template <template <typename ...> class F>
  149. struct template_t {
  150. template <typename ...T>
  151. struct apply {
  152. using type = F<T...>;
  153. };
  154. template <typename ...T, typename = std::enable_if_t<
  155. template_detail::specialization_is_valid<F, template_detail::args<typename T::type...>>::value
  156. >>
  157. constexpr auto operator()(T const& ...) const
  158. { return hana::type<F<typename T::type...>>{}; }
  159. };
  160. //////////////////////////////////////////////////////////////////////////
  161. // metafunction
  162. //////////////////////////////////////////////////////////////////////////
  163. template <template <typename ...> class F>
  164. struct metafunction_t {
  165. template <typename ...T>
  166. using apply = F<T...>;
  167. template <typename ...T>
  168. constexpr hana::type<typename F<typename T::type...>::type>
  169. operator()(T const& ...) const { return {}; }
  170. };
  171. //////////////////////////////////////////////////////////////////////////
  172. // metafunction_class
  173. //////////////////////////////////////////////////////////////////////////
  174. namespace detail {
  175. template <typename F, typename ...T>
  176. struct always_first { using type = F; };
  177. }
  178. template <typename F>
  179. struct metafunction_class_t {
  180. template <typename ...T>
  181. using apply = typename detail::always_first<F, T...>::type::template apply<T...>;
  182. template <typename ...T>
  183. constexpr hana::type<typename detail::always_first<F, T...>::type::template apply<typename T::type...>::type>
  184. operator()(T const& ...) const { return {}; }
  185. };
  186. //////////////////////////////////////////////////////////////////////////
  187. // Metafunction
  188. //////////////////////////////////////////////////////////////////////////
  189. template <template <typename ...> class F>
  190. struct Metafunction<template_t<F>> {
  191. static constexpr bool value = true;
  192. };
  193. template <template <typename ...> class F>
  194. struct Metafunction<metafunction_t<F>> {
  195. static constexpr bool value = true;
  196. };
  197. template <typename F>
  198. struct Metafunction<metafunction_class_t<F>> {
  199. static constexpr bool value = true;
  200. };
  201. //////////////////////////////////////////////////////////////////////////
  202. // integral
  203. //////////////////////////////////////////////////////////////////////////
  204. template <typename F>
  205. struct integral_t {
  206. template <typename ...T, typename Result =
  207. typename detail::always_first<F, T...>::type::template apply<typename T::type...>::type
  208. >
  209. constexpr Result operator()(T const& ...) const {
  210. return Result{};
  211. }
  212. };
  213. //////////////////////////////////////////////////////////////////////////
  214. // Operators
  215. //////////////////////////////////////////////////////////////////////////
  216. namespace detail {
  217. template <>
  218. struct comparable_operators<type_tag> {
  219. static constexpr bool value = true;
  220. };
  221. }
  222. //////////////////////////////////////////////////////////////////////////
  223. // Comparable
  224. //////////////////////////////////////////////////////////////////////////
  225. template <>
  226. struct equal_impl<type_tag, type_tag> {
  227. template <typename T, typename U>
  228. static constexpr auto apply(basic_type<T> const&, basic_type<U> const&)
  229. { return hana::false_c; }
  230. template <typename T>
  231. static constexpr auto apply(basic_type<T> const&, basic_type<T> const&)
  232. { return hana::true_c; }
  233. };
  234. //////////////////////////////////////////////////////////////////////////
  235. // Hashable
  236. //////////////////////////////////////////////////////////////////////////
  237. template <>
  238. struct hash_impl<hana::type_tag> {
  239. template <typename T>
  240. static constexpr T apply(T const& t)
  241. { return t; }
  242. };
  243. }} // end namespace boost::hana
  244. #endif // !BOOST_HANA_TYPE_HPP