integer_sequence.hpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /*!
  2. @file
  3. Adapts `std::integer_sequence` for use with Hana.
  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_EXT_STD_INTEGER_SEQUENCE_HPP
  9. #define BOOST_HANA_EXT_STD_INTEGER_SEQUENCE_HPP
  10. #include <boost/hana/bool.hpp>
  11. #include <boost/hana/config.hpp>
  12. #include <boost/hana/detail/fast_and.hpp>
  13. #include <boost/hana/ext/std/integral_constant.hpp>
  14. #include <boost/hana/fwd/at.hpp>
  15. #include <boost/hana/fwd/core/tag_of.hpp>
  16. #include <boost/hana/fwd/drop_front.hpp>
  17. #include <boost/hana/fwd/equal.hpp>
  18. #include <boost/hana/fwd/is_empty.hpp>
  19. #include <boost/hana/fwd/unpack.hpp>
  20. #include <cstddef>
  21. #include <type_traits>
  22. #include <utility>
  23. #ifdef BOOST_HANA_DOXYGEN_INVOKED
  24. namespace std {
  25. //! @ingroup group-ext-std
  26. //! Adaptation of `std::integer_sequence` for Hana.
  27. //!
  28. //!
  29. //!
  30. //! Modeled concepts
  31. //! ----------------
  32. //! 1. `Comparable`\n
  33. //! Two `std::integer_sequence`s are equal if and only if they have the
  34. //! same number of elements, and if corresponding elements compare equal.
  35. //! The types of the elements held in both `integer_sequence`s may be
  36. //! different, as long as they can be compared.
  37. //! @include example/ext/std/integer_sequence/comparable.cpp
  38. //!
  39. //! 2. `Foldable`\n
  40. //! Folding an `integer_sequence` is equivalent to folding a sequence of
  41. //! `std::integral_constant`s with the corresponding types.
  42. //! @include example/ext/std/integer_sequence/foldable.cpp
  43. //!
  44. //! 3. `Iterable`\n
  45. //! Iterating over an `integer_sequence` is equivalent to iterating over
  46. //! a sequence of the corresponding `std::integral_constant`s.
  47. //! @include example/ext/std/integer_sequence/iterable.cpp
  48. //!
  49. //! 4. `Searchable`\n
  50. //! Searching through an `integer_sequence` is equivalent to searching
  51. //! through the corresponding sequence of `std::integral_constant`s.
  52. //! @include example/ext/std/integer_sequence/searchable.cpp
  53. template <typename T, T ...v>
  54. struct integer_sequence { };
  55. }
  56. #endif
  57. BOOST_HANA_NAMESPACE_BEGIN
  58. namespace ext { namespace std { struct integer_sequence_tag; }}
  59. template <typename T, T ...v>
  60. struct tag_of<std::integer_sequence<T, v...>> {
  61. using type = ext::std::integer_sequence_tag;
  62. };
  63. //////////////////////////////////////////////////////////////////////////
  64. // Comparable
  65. //////////////////////////////////////////////////////////////////////////
  66. template <>
  67. struct equal_impl<ext::std::integer_sequence_tag, ext::std::integer_sequence_tag> {
  68. template <typename X, X ...xs, typename Y, Y ...ys>
  69. static constexpr hana::bool_<detail::fast_and<(xs == ys)...>::value>
  70. apply(std::integer_sequence<X, xs...> const&, std::integer_sequence<Y, ys...> const&)
  71. { return {}; }
  72. template <typename Xs, typename Ys>
  73. static constexpr hana::false_ apply(Xs const&, Ys const&, ...)
  74. { return {}; }
  75. };
  76. //////////////////////////////////////////////////////////////////////////
  77. // Foldable
  78. //////////////////////////////////////////////////////////////////////////
  79. template <>
  80. struct unpack_impl<ext::std::integer_sequence_tag> {
  81. template <typename T, T ...v, typename F>
  82. static constexpr decltype(auto)
  83. apply(std::integer_sequence<T, v...> const&, F&& f) {
  84. return static_cast<F&&>(f)(std::integral_constant<T, v>{}...);
  85. }
  86. };
  87. //////////////////////////////////////////////////////////////////////////
  88. // Iterable
  89. //////////////////////////////////////////////////////////////////////////
  90. template <>
  91. struct at_impl<ext::std::integer_sequence_tag> {
  92. template <typename T, T ...v, typename N>
  93. static constexpr auto apply(std::integer_sequence<T, v...> const&, N const&) {
  94. constexpr std::size_t n = N::value;
  95. constexpr T values_[] = {v...};
  96. return std::integral_constant<T, values_[n]>{};
  97. }
  98. };
  99. template <>
  100. struct drop_front_impl<ext::std::integer_sequence_tag> {
  101. template <std::size_t n, typename T, T ...t, std::size_t ...i>
  102. static constexpr auto drop_front_helper(std::integer_sequence<T, t...>,
  103. std::index_sequence<i...>)
  104. {
  105. constexpr T ts[sizeof...(t)+1] = {t...}; // avoid 0-sized array
  106. return std::integer_sequence<T, ts[n + i]...>{};
  107. }
  108. template <typename T, T ...t, typename N>
  109. static constexpr auto apply(std::integer_sequence<T, t...> ts, N const&) {
  110. constexpr std::size_t n = N::value;
  111. constexpr std::size_t len = sizeof...(t);
  112. return drop_front_helper<n>(ts,
  113. std::make_index_sequence<(n < len ? len - n : 0)>{});
  114. }
  115. };
  116. template <>
  117. struct is_empty_impl<ext::std::integer_sequence_tag> {
  118. template <typename T, T ...xs>
  119. static constexpr auto apply(std::integer_sequence<T, xs...> const&)
  120. { return hana::bool_c<sizeof...(xs) == 0>; }
  121. };
  122. BOOST_HANA_NAMESPACE_END
  123. #endif // !BOOST_HANA_EXT_STD_INTEGER_SEQUENCE_HPP