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