libcarla/include/system/boost/hana/sort.hpp
2024-10-18 13:19:59 +08:00

274 lines
8.7 KiB
C++

/*!
@file
Defines `boost::hana::sort`.
@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_SORT_HPP
#define BOOST_HANA_SORT_HPP
#include <boost/hana/fwd/sort.hpp>
#include <boost/hana/at.hpp>
#include <boost/hana/concept/sequence.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/core/make.hpp>
#include <boost/hana/detail/nested_by.hpp> // required by fwd decl
#include <boost/hana/length.hpp>
#include <boost/hana/less.hpp>
#include <utility> // std::declval, std::index_sequence
namespace boost { namespace hana {
//! @cond
template <typename Xs, typename Predicate>
constexpr auto sort_t::operator()(Xs&& xs, Predicate&& pred) const {
using S = typename hana::tag_of<Xs>::type;
using Sort = BOOST_HANA_DISPATCH_IF(sort_impl<S>,
hana::Sequence<S>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Sequence<S>::value,
"hana::sort(xs, predicate) requires 'xs' to be a Sequence");
#endif
return Sort::apply(static_cast<Xs&&>(xs),
static_cast<Predicate&&>(pred));
}
template <typename Xs>
constexpr auto sort_t::operator()(Xs&& xs) const {
using S = typename hana::tag_of<Xs>::type;
using Sort = BOOST_HANA_DISPATCH_IF(sort_impl<S>,
hana::Sequence<S>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Sequence<S>::value,
"hana::sort(xs) requires 'xs' to be a Sequence");
#endif
return Sort::apply(static_cast<Xs&&>(xs));
}
//! @endcond
namespace detail {
template <typename Xs, typename Pred>
struct sort_predicate {
template <std::size_t I, std::size_t J>
using apply = decltype(std::declval<Pred>()(
hana::at_c<I>(std::declval<Xs>()),
hana::at_c<J>(std::declval<Xs>())
));
};
template <typename Left, typename Right>
struct concat;
template <std::size_t ...l, std::size_t ...r>
struct concat<std::index_sequence<l...>, std::index_sequence<r...>> {
using type = std::index_sequence<l..., r...>;
};
template <typename Pred, bool PickRight, typename Left, typename Right>
struct merge;
template <
typename Pred,
std::size_t l0,
std::size_t l1,
std::size_t ...l,
std::size_t r0,
std::size_t ...r>
struct merge<
Pred,
false,
std::index_sequence<l0, l1, l...>,
std::index_sequence<r0, r...>
> {
using type = typename concat<
std::index_sequence<l0>,
typename merge<
Pred,
(bool)Pred::template apply<r0, l1>::value,
std::index_sequence<l1, l...>,
std::index_sequence<r0, r...>
>::type
>::type;
};
template <
typename Pred,
std::size_t l0,
std::size_t r0,
std::size_t ...r>
struct merge<
Pred,
false,
std::index_sequence<l0>,
std::index_sequence<r0, r...>
> {
using type = std::index_sequence<l0, r0, r...>;
};
template <
typename Pred,
std::size_t l0,
std::size_t ...l,
std::size_t r0,
std::size_t r1,
std::size_t ...r>
struct merge<
Pred,
true,
std::index_sequence<l0, l...>,
std::index_sequence<r0, r1, r...>
> {
using type = typename concat<
std::index_sequence<r0>,
typename merge<
Pred,
(bool)Pred::template apply<r1, l0>::value,
std::index_sequence<l0, l...>,
std::index_sequence<r1, r...>
>::type
>::type;
};
template <
typename Pred,
std::size_t l0,
std::size_t ...l,
std::size_t r0>
struct merge<
Pred,
true,
std::index_sequence<l0, l...>,
std::index_sequence<r0>
> {
using type = std::index_sequence<r0, l0, l...>;
};
template <typename Pred, typename Left, typename Right>
struct merge_helper;
template <
typename Pred,
std::size_t l0,
std::size_t ...l,
std::size_t r0,
std::size_t ...r>
struct merge_helper<
Pred,
std::index_sequence<l0, l...>,
std::index_sequence<r0, r...>
> {
using type = typename merge<
Pred,
(bool)Pred::template apply<r0, l0>::value,
std::index_sequence<l0, l...>,
std::index_sequence<r0, r...>
>::type;
};
// split templated structure, Nr represents the number of elements
// from Right to move to Left
// There are two specializations:
// The first handles the generic case (Nr > 0)
// The second handles the stop condition (Nr == 0)
// These two specializations are not strictly ordered as
// the first cannot match Nr==0 && empty Right
// the second cannot match Nr!=0
// std::enable_if<Nr!=0> is therefore required to make sure these two
// specializations will never both be candidates during an overload
// resolution (otherwise ambiguity occurs for Nr==0 and non-empty Right)
template <std::size_t Nr, typename Left, typename Right, typename=void>
struct split;
template <
std::size_t Nr,
std::size_t ...l,
std::size_t ...r,
std::size_t r0>
struct split<
Nr,
std::index_sequence<l...>,
std::index_sequence<r0, r...>,
typename std::enable_if<Nr!=0>::type
> {
using sp = split<
Nr-1,
std::index_sequence<l..., r0>,
std::index_sequence<r...>
>;
using left = typename sp::left;
using right = typename sp::right;
};
template <std::size_t ...l, std::size_t ...r>
struct split<0, std::index_sequence<l...>, std::index_sequence<r...>> {
using left = std::index_sequence<l...>;
using right = std::index_sequence<r...>;
};
template <typename Pred, typename Sequence>
struct merge_sort_impl;
template <typename Pred, std::size_t ...seq>
struct merge_sort_impl<Pred, std::index_sequence<seq...>> {
using sequence = std::index_sequence<seq...>;
using sp = split<
sequence::size() / 2,
std::index_sequence<>,
sequence
>;
using type = typename merge_helper<
Pred,
typename merge_sort_impl<Pred, typename sp::left>::type,
typename merge_sort_impl<Pred, typename sp::right>::type
>::type;
};
template <typename Pred, std::size_t x>
struct merge_sort_impl<Pred, std::index_sequence<x>> {
using type = std::index_sequence<x>;
};
template <typename Pred>
struct merge_sort_impl<Pred, std::index_sequence<>> {
using type = std::index_sequence<>;
};
} // end namespace detail
template <typename S, bool condition>
struct sort_impl<S, when<condition>> : default_ {
template <typename Xs, std::size_t ...i>
static constexpr auto apply_impl(Xs&& xs, std::index_sequence<i...>) {
return hana::make<S>(hana::at_c<i>(static_cast<Xs&&>(xs))...);
}
template <typename Xs, typename Pred>
static constexpr auto apply(Xs&& xs, Pred const&) {
constexpr std::size_t Len = decltype(hana::length(xs))::value;
using Indices = typename detail::merge_sort_impl<
detail::sort_predicate<Xs&&, Pred>,
std::make_index_sequence<Len>
>::type;
return apply_impl(static_cast<Xs&&>(xs), Indices{});
}
template <typename Xs>
static constexpr auto apply(Xs&& xs)
{ return sort_impl::apply(static_cast<Xs&&>(xs), hana::less); }
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_SORT_HPP