/*! @file Defines `boost::hana::sort`. @copyright Louis Dionne 2013-2016 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_SORT_HPP #define BOOST_HANA_SORT_HPP #include #include #include #include #include #include #include // required by fwd decl #include #include #include // std::declval, std::index_sequence BOOST_HANA_NAMESPACE_BEGIN //! @cond template constexpr auto sort_t::operator()(Xs&& xs, Predicate&& pred) const { using S = typename hana::tag_of::type; using Sort = BOOST_HANA_DISPATCH_IF(sort_impl, hana::Sequence::value ); #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS static_assert(hana::Sequence::value, "hana::sort(xs, predicate) requires 'xs' to be a Sequence"); #endif return Sort::apply(static_cast(xs), static_cast(pred)); } template constexpr auto sort_t::operator()(Xs&& xs) const { using S = typename hana::tag_of::type; using Sort = BOOST_HANA_DISPATCH_IF(sort_impl, hana::Sequence::value ); #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS static_assert(hana::Sequence::value, "hana::sort(xs) requires 'xs' to be a Sequence"); #endif return Sort::apply(static_cast(xs)); } //! @endcond namespace detail { template struct sort_predicate { template using apply = decltype(std::declval()( hana::at_c(std::declval()), hana::at_c(std::declval()) )); }; template struct insert; // We did not find the insertion point; continue processing elements // recursively. template < typename Pred, std::size_t Insert, std::size_t ...Left, std::size_t Right1, std::size_t Right2, std::size_t ...Right > struct insert, Right1, Right2, Right... > { using type = typename insert< Pred, Insert, (bool)Pred::template apply::value, std::index_sequence, Right2, Right... >::type; }; // We did not find the insertion point, but there is only one element // left. We insert at the end of the list, and we're done. template struct insert, Last> { using type = std::index_sequence; }; // We found the insertion point, we're done. template struct insert, Right...> { using type = std::index_sequence; }; template struct insertion_sort_impl; template struct insertion_sort_impl, T, Ts...> { using type = typename insertion_sort_impl< Pred, typename insert< Pred, T, (bool)Pred::template apply::value, std::index_sequence<>, Result1, Result... >::type, Ts... >::type; }; template struct insertion_sort_impl, T, Ts...> { using type = typename insertion_sort_impl< Pred, std::index_sequence, Ts... >::type; }; template struct insertion_sort_impl { using type = Result; }; template struct sort_helper; template struct sort_helper> { using type = typename insertion_sort_impl< Pred, std::index_sequence<>, i... >::type; }; } // end namespace detail template struct sort_impl> : default_ { template static constexpr auto apply_impl(Xs&& xs, std::index_sequence) { return hana::make(hana::at_c(static_cast(xs))...); } template static constexpr auto apply(Xs&& xs, Pred const&) { constexpr std::size_t Len = decltype(hana::length(xs))::value; using Indices = typename detail::sort_helper< detail::sort_predicate, std::make_index_sequence >::type; return apply_impl(static_cast(xs), Indices{}); } template static constexpr auto apply(Xs&& xs) { return sort_impl::apply(static_cast(xs), hana::less); } }; BOOST_HANA_NAMESPACE_END #endif // !BOOST_HANA_SORT_HPP