Program Listing for File partition.hpp
↰ Return to documentation for file (include/partition.hpp
)
#pragma once
#include "htlist.hpp"
#include "predicates.hpp"
#include <type_traits>
namespace ctql {
namespace detail {
// partition_by_impl<Pivot, Rel, HTList<...>>
// Produces two buckets:
// - pass: elements where Rel<Pivot, Elem>::value is true
// - fail: the remaining elements
template <typename Pivot, template <typename, typename> class Rel, typename List>
struct partition_by_impl;
// Empty list -> both buckets empty.
template <typename Pivot, template <typename, typename> class Rel>
struct partition_by_impl<Pivot, Rel, HTList<>> {
using pass = HTList<>;
using fail = HTList<>;
};
// Step: peel head H; recurse on tail Ts...
template <typename Pivot,
template <typename, typename> class Rel,
typename H,
typename... Ts>
struct partition_by_impl<Pivot, Rel, HTList<H, Ts...>> {
private:
using rest = partition_by_impl<Pivot, Rel, HTList<Ts...>>;
public:
using pass = std::conditional_t<
Rel<Pivot, H>::value,
typename append<HTList<H>, typename rest::pass>::type,
typename rest::pass>;
using fail = std::conditional_t<
Rel<Pivot, H>::value,
typename rest::fail,
typename append<HTList<H>, typename rest::fail>::type>;
};
} // namespace detail
template <typename Pivot, template <typename, typename> class Rel, typename... Ts>
struct partition_by {
using impl = detail::partition_by_impl<Pivot, Rel, detail::HTList<Ts...>>;
using pass = typename impl::pass; // kept / left bucket
using fail = typename impl::fail; // rejected / right bucket
using concat = typename detail::HTList<pass, fail>; // pair as a two-element typelist
};
template <typename Pivot, template <typename, typename> class Rel, typename... Ts>
using filter_by = typename partition_by<Pivot, Rel, Ts...>::pass;
template <typename Pivot, template <typename, typename> class Rel, typename... Ts>
using reject_if_by = typename partition_by<Pivot, Rel, Ts...>::fail;
template <typename Pivot,
template <typename, typename> class Rel,
template <typename> class KeyOf = Size,
typename... Ts>
using partition_by_key = partition_by<Pivot, Rel, KeyOf<Ts>...>;
} // namespace ctql