types.hpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*!
  2. @file
  3. Defines `boost::hana::experimental::types`.
  4. @copyright Louis Dionne 2013-2017
  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_EXPERIMENTAL_TYPES_HPP
  9. #define BOOST_HANA_EXPERIMENTAL_TYPES_HPP
  10. #include <boost/hana/bool.hpp>
  11. #include <boost/hana/concept/metafunction.hpp>
  12. #include <boost/hana/config.hpp>
  13. #include <boost/hana/detail/any_of.hpp>
  14. #include <boost/hana/detail/type_at.hpp>
  15. #include <boost/hana/fwd/at.hpp>
  16. #include <boost/hana/fwd/contains.hpp>
  17. #include <boost/hana/fwd/core/tag_of.hpp>
  18. #include <boost/hana/fwd/equal.hpp>
  19. #include <boost/hana/fwd/is_empty.hpp>
  20. #include <boost/hana/fwd/transform.hpp>
  21. #include <boost/hana/fwd/unpack.hpp>
  22. #include <boost/hana/type.hpp>
  23. #include <cstddef>
  24. #include <type_traits>
  25. #include <utility>
  26. BOOST_HANA_NAMESPACE_BEGIN
  27. namespace experimental {
  28. //! @ingroup group-experimental
  29. //! Container optimized for holding types.
  30. //!
  31. //! It is often useful to manipulate a sequence that contains types
  32. //! only, without any associated runtime value. This container allows
  33. //! storing and manipulating pure types in a much more compile-time
  34. //! efficient manner than using `hana::tuple`, which must assume that
  35. //! its contents might have runtime values.
  36. template <typename ...T>
  37. struct types;
  38. struct types_tag;
  39. template <typename ...T>
  40. struct types { };
  41. } // end namespace experimental
  42. template <typename ...T>
  43. struct tag_of<experimental::types<T...>> {
  44. using type = experimental::types_tag;
  45. };
  46. // Foldable
  47. template <>
  48. struct unpack_impl<hana::experimental::types_tag> {
  49. template <typename ...T, typename F, typename = typename std::enable_if<
  50. !hana::Metafunction<F>::value
  51. >::type>
  52. static constexpr decltype(auto) apply(hana::experimental::types<T...> const&, F&& f) {
  53. return static_cast<F&&>(f)(hana::type<T>{}...);
  54. }
  55. template <typename ...T, typename F, typename = typename std::enable_if<
  56. hana::Metafunction<F>::value
  57. >::type>
  58. static constexpr hana::type<typename F::template apply<T...>::type>
  59. apply(hana::experimental::types<T...> const&, F const&) { return {}; }
  60. };
  61. // Functor
  62. template <>
  63. struct transform_impl<hana::experimental::types_tag> {
  64. template <typename ...T, typename F, typename = typename std::enable_if<
  65. !hana::Metafunction<F>::value
  66. >::type>
  67. static constexpr auto apply(hana::experimental::types<T...> const&, F&& f)
  68. -> hana::experimental::types<typename decltype(+f(hana::type<T>{}))::type...>
  69. { return {}; }
  70. template <typename ...T, typename F, typename = typename std::enable_if<
  71. hana::Metafunction<F>::value
  72. >::type>
  73. static constexpr hana::experimental::types<typename F::template apply<T>::type...>
  74. apply(hana::experimental::types<T...> const&, F const&) { return {}; }
  75. };
  76. // Iterable
  77. template <>
  78. struct at_impl<hana::experimental::types_tag> {
  79. template <typename ...T, typename N>
  80. static constexpr auto
  81. apply(hana::experimental::types<T...> const&, N const&) {
  82. using Nth = typename detail::type_at<N::value, T...>::type;
  83. return hana::type<Nth>{};
  84. }
  85. };
  86. template <>
  87. struct is_empty_impl<hana::experimental::types_tag> {
  88. template <typename ...T>
  89. static constexpr hana::bool_<sizeof...(T) == 0>
  90. apply(hana::experimental::types<T...> const&)
  91. { return {}; }
  92. };
  93. template <>
  94. struct drop_front_impl<hana::experimental::types_tag> {
  95. template <std::size_t n, typename ...T, std::size_t ...i>
  96. static hana::experimental::types<typename detail::type_at<i + n, T...>::type...>
  97. helper(std::index_sequence<i...>);
  98. template <typename ...T, typename N>
  99. static constexpr auto
  100. apply(hana::experimental::types<T...> const&, N const&) {
  101. constexpr std::size_t n = N::value > sizeof...(T) ? sizeof...(T) : N::value;
  102. using Indices = std::make_index_sequence<sizeof...(T) - n>;
  103. return decltype(helper<n, T...>(Indices{})){};
  104. }
  105. };
  106. // Searchable
  107. template <>
  108. struct contains_impl<hana::experimental::types_tag> {
  109. template <typename U>
  110. struct is_same_as {
  111. template <typename T>
  112. struct apply {
  113. static constexpr bool value = std::is_same<U, T>::value;
  114. };
  115. };
  116. template <typename ...T, typename U>
  117. static constexpr auto apply(hana::experimental::types<T...> const&, U const&)
  118. -> hana::bool_<
  119. detail::any_of<is_same_as<typename U::type>::template apply, T...>::value
  120. >
  121. { return {}; }
  122. static constexpr hana::false_ apply(...) { return {}; }
  123. };
  124. // Comparable
  125. template <>
  126. struct equal_impl<hana::experimental::types_tag, hana::experimental::types_tag> {
  127. template <typename Types>
  128. static constexpr hana::true_ apply(Types const&, Types const&)
  129. { return {}; }
  130. template <typename Ts, typename Us>
  131. static constexpr hana::false_ apply(Ts const&, Us const&)
  132. { return {}; }
  133. };
  134. BOOST_HANA_NAMESPACE_END
  135. #endif // !BOOST_HANA_EXPERIMENTAL_TYPES_HPP