/*! @file Defines `boost::hana::slice` and `boost::hana::slice_c`. @copyright Louis Dionne 2013-2017 Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) */ #ifndef BOOST_HANA_SLICE_HPP #define BOOST_HANA_SLICE_HPP #include #include #include #include #include #include #include #include #include #include #include BOOST_HANA_NAMESPACE_BEGIN //! @cond template constexpr auto slice_t::operator()(Xs&& xs, Indices&& indices) const { using S = typename hana::tag_of::type; using Slice = BOOST_HANA_DISPATCH_IF(slice_impl, hana::Sequence::value && hana::Foldable::value ); #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS static_assert(hana::Sequence::value, "hana::slice(xs, indices) requires 'xs' to be a Sequence"); static_assert(hana::Foldable::value, "hana::slice(xs, indices) requires 'indices' to be Foldable"); #endif return Slice::apply(static_cast(xs), static_cast(indices)); } //! @endcond namespace detail { template struct take_arbitrary { Xs& xs; using S = typename hana::tag_of::type; template constexpr auto operator()(N const& ...) const { return hana::make(hana::at_c(xs)...); } }; } template struct slice_impl> : default_ { template static constexpr auto from_offset(Xs&& xs, std::index_sequence) { return hana::make(hana::at_c(static_cast(xs))...); } template static constexpr auto apply(Xs&& xs, hana::range const&) { return slice_impl::from_offset( static_cast(xs), std::make_index_sequence{} ); } //! @todo //! Since we have the right to specify the same index more than once, //! we can't move from the elements of the source sequence even if it //! is a temporary object: we could end up double-moving. Perhaps it //! would be possible to determine the indices from which we can move //! without incurring a too large compile-time penalty? template static constexpr auto apply(Xs const& xs, Indices const& indices) { return hana::unpack(indices, detail::take_arbitrary{xs}); } }; template struct slice_c_t { template constexpr auto operator()(Xs&& xs) const { return hana::slice(static_cast(xs), hana::range_c); } }; BOOST_HANA_NAMESPACE_END #endif // !BOOST_HANA_SLICE_HPP