Program Listing for File sorted.hpp

Return to documentation for file (include/sorted.hpp)

#pragma once

#include "partition.hpp"
#include "predicates.hpp"
#include "htlist.hpp"


namespace ctql {

    enum class Order { Asc, Desc };

    template <Order Ord, typename List>
    struct sort_list;

    template <Order Ord>
    struct sort_list<Ord, detail::HTList<>> {
        using type = detail::HTList<>;
    };

    template <Order Ord, HasStaticSize T0, HasStaticSize... TRest>
    struct sort_list<Ord, detail::HTList<T0, TRest...>> {
    private:
        // Choose relational operators based on order:
        //   Asc:  Left = "<",  Right = ">="
        //   Desc: Left = ">",  Right = "<="
        using LeftRel  = std::conditional_t<Ord == Order::Asc,  op_type<"<"_ct>,  op_type<">"_ct>>;
        using RightRel = std::conditional_t<Ord == Order::Asc,  op_type<">="_ct>, op_type<"<="_ct>>;

        // Partition the tail TRest... with respect to pivot T0.
        // P::pass  => elements on the Left side (strict compare vs pivot)
        // Not-pass => elements on the Right side (>= or <= vs pivot)
        using P = partition_by<T0, LeftRel::template pred, TRest...>;
        using LeftSorted = typename sort_list<Ord, typename P::pass>::type;

        using RightUnsorted = filter_by<T0, RightRel::template pred, TRest...>;
        using RightSorted   = typename sort_list<Ord, RightUnsorted>::type;

    public:
        // Concatenate: LeftSorted ++ [T0] ++ RightSorted
        using type = typename detail::append<
            typename detail::append<LeftSorted, detail::HTList<T0>>::type,
            RightSorted
        >::type;
    };

    template <Order Ord = Order::Asc, template <typename> class KeyOf = Size, typename... Ts>
    using TypeSort = typename sort_list<Ord, detail::HTList<KeyOf<Ts>...>>::type;

} // namespace ctql