3 Defines `boost::hana::slice` and `boost::hana::slice_c`.
5 @copyright Louis Dionne 2013-2016
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)
10 #ifndef BOOST_HANA_SLICE_HPP
11 #define BOOST_HANA_SLICE_HPP
13 #include <boost/hana/fwd/slice.hpp>
15 #include <boost/hana/at.hpp>
16 #include <boost/hana/concept/foldable.hpp>
17 #include <boost/hana/concept/sequence.hpp>
18 #include <boost/hana/config.hpp>
19 #include <boost/hana/core/dispatch.hpp>
20 #include <boost/hana/core/make.hpp>
21 #include <boost/hana/range.hpp>
22 #include <boost/hana/unpack.hpp>
28 BOOST_HANA_NAMESPACE_BEGIN
30 template <typename Xs, typename Indices>
31 constexpr auto slice_t::operator()(Xs&& xs, Indices&& indices) const {
32 using S = typename hana::tag_of<Xs>::type;
33 using Slice = BOOST_HANA_DISPATCH_IF(slice_impl<S>,
34 hana::Sequence<S>::value &&
35 hana::Foldable<Indices>::value
38 #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
39 static_assert(hana::Sequence<S>::value,
40 "hana::slice(xs, indices) requires 'xs' to be a Sequence");
42 static_assert(hana::Foldable<Indices>::value,
43 "hana::slice(xs, indices) requires 'indices' to be Foldable");
46 return Slice::apply(static_cast<Xs&&>(xs), static_cast<Indices&&>(indices));
51 template <typename Xs>
52 struct take_arbitrary {
54 using S = typename hana::tag_of<Xs>::type;
56 template <typename ...N>
57 constexpr auto operator()(N const& ...) const {
58 return hana::make<S>(hana::at_c<N::value>(xs)...);
63 template <typename S, bool condition>
64 struct slice_impl<S, when<condition>> : default_ {
65 template <std::size_t from, typename Xs, std::size_t ...i>
66 static constexpr auto from_offset(Xs&& xs, std::index_sequence<i...>) {
67 return hana::make<S>(hana::at_c<from + i>(static_cast<Xs&&>(xs))...);
70 template <typename Xs, typename T, T from, T to>
71 static constexpr auto apply(Xs&& xs, hana::range<T, from, to> const&) {
72 return slice_impl::from_offset<from>(
73 static_cast<Xs&&>(xs), std::make_index_sequence<to - from>{}
78 //! Since we have the right to specify the same index more than once,
79 //! we can't move from the elements of the source sequence even if it
80 //! is a temporary object: we could end up double-moving. Perhaps it
81 //! would be possible to determine the indices from which we can move
82 //! without incurring a too large compile-time penalty?
83 template <typename Xs, typename Indices>
84 static constexpr auto apply(Xs const& xs, Indices const& indices) {
85 return hana::unpack(indices, detail::take_arbitrary<Xs const>{xs});
89 template <std::size_t from, std::size_t to>
91 template <typename Xs>
92 constexpr auto operator()(Xs&& xs) const {
93 return hana::slice(static_cast<Xs&&>(xs),
94 hana::range_c<std::size_t, from, to>);
97 BOOST_HANA_NAMESPACE_END
99 #endif // !BOOST_HANA_SLICE_HPP