Skip to content

Instantly share code, notes, and snippets.

@tatsuhiro-t
Created November 7, 2017 15:17
Show Gist options
  • Save tatsuhiro-t/ac141b1d8c303be5151369d2c1bf156d to your computer and use it in GitHub Desktop.
Save tatsuhiro-t/ac141b1d8c303be5151369d2c1bf156d to your computer and use it in GitHub Desktop.
Compile-time merge sort
#include <cstdint>
#include <type_traits>
#include <array>
#include <iostream>
#include <iterator>
template <int64_t... Args> struct Array {
const std::array<int64_t, sizeof...(Args)> data;
constexpr Array() : data{{Args...}} {}
};
template <typename L, typename R, typename D, bool x> struct Take;
template <typename L, typename R, typename D> struct MergeAcc;
template <int64_t LArg, int64_t... LRest, template <int64_t...> class L,
int64_t RArg, int64_t... RRest, template <int64_t...> class R,
int64_t... DArgs, template <int64_t...> class D>
struct Take<L<LArg, LRest...>, R<RArg, RRest...>, D<DArgs...>, true> {
using result_type = typename MergeAcc<L<LRest...>, R<RArg, RRest...>,
D<DArgs..., LArg>>::result_type;
};
template <int64_t LArg, int64_t... LRest, template <int64_t...> class L,
int64_t RArg, int64_t... RRest, template <int64_t...> class R,
int64_t... DArgs, template <int64_t...> class D>
struct Take<L<LArg, LRest...>, R<RArg, RRest...>, D<DArgs...>, false> {
using result_type = typename MergeAcc<L<LArg, LRest...>, R<RRest...>,
D<DArgs..., RArg>>::result_type;
};
template <int64_t LArg, int64_t... LRest, template <int64_t...> class L,
int64_t RArg, int64_t... RRest, template <int64_t...> class R,
int64_t... DArgs, template <int64_t...> class D>
struct MergeAcc<L<LArg, LRest...>, R<RArg, RRest...>, D<DArgs...>> {
using result_type = typename Take<L<LArg, LRest...>, R<RArg, RRest...>,
D<DArgs...>, (LArg < RArg)>::result_type;
};
template <template <int64_t...> class L, int64_t... RArgs,
template <int64_t...> class R, int64_t... DArgs,
template <int64_t...> class D>
struct MergeAcc<L<>, R<RArgs...>, D<DArgs...>> {
using result_type = D<DArgs..., RArgs...>;
};
template <int64_t... LArgs, template <int64_t...> class L,
template <int64_t...> class R, int64_t... DArgs,
template <int64_t...> class D>
struct MergeAcc<L<LArgs...>, R<>, D<DArgs...>> {
using result_type = D<DArgs..., LArgs...>;
};
template <typename L, typename R> struct Merge {
using result_type = typename MergeAcc<L, R, Array<>>::result_type;
};
template <std::size_t N, typename A, typename D, typename = void>
struct FirstAcc;
template <std::size_t N, int64_t AArg, int64_t... ARest,
template <int64_t...> class A, int64_t... DArgs,
template <int64_t...> class D>
struct FirstAcc<N, A<AArg, ARest...>, D<DArgs...>,
typename std::enable_if<N != 0>::type> {
using result_type =
typename FirstAcc<N - 1, A<ARest...>, D<DArgs..., AArg>>::result_type;
};
template <typename A, typename D> struct FirstAcc<0, A, D, void> {
using result_type = D;
};
template <std::size_t N, typename A> struct First {
using result_type = typename FirstAcc<N, A, Array<>>::result_type;
};
template <std::size_t N, typename A, typename = void> struct Second;
template <std::size_t N, int64_t AArg, int64_t... ARest,
template <int64_t...> class A>
struct Second<N, A<AArg, ARest...>, typename std::enable_if<N != 0>::type> {
using result_type = typename Second<N - 1, A<ARest...>>::result_type;
};
template <typename A> struct Second<0, A, void> { using result_type = A; };
template <std::size_t N, typename A> struct SortArray {
using result_type = typename Merge<
typename SortArray<N / 2,
typename First<N / 2, A>::result_type>::result_type,
typename SortArray<N - N / 2, typename Second<N / 2, A>::result_type>::
result_type>::result_type;
};
template <typename A> struct SortArray<0, A> { using result_type = A; };
template <typename A> struct SortArray<1, A> { using result_type = A; };
template <int64_t... Args> struct MergeSort {
using result_type =
typename SortArray<sizeof...(Args), Array<Args...>>::result_type;
};
template <typename X> struct TD;
int main() {
constexpr MergeSort<17, 50, 68, 35, 93, 36, 99, 80, 4, 55, 11, 6, 87, 45, 39,
81, 48, 51, 14, 33, 88, 97, 78, 67, 76, 42, 64, 60, 22,
75, 90, 54, 24, 59, 41, 43, 66, 62, 38, 3, 91, 9, 10, 15,
82, 95, 96, 85, 31, 32, 19, 77, 46, 8, 84, 63, 7, 12, 1,
16, 40, 53, 30, 23, 79, 58, 2, 89, 25, 70, 28, 21, 47, 92,
73, 86, 56, 65, 27, 52, 61, 34, 72, 20, 49, 83, 98, 13,
69, 29, 26, 5, 37, 18, 57, 94, 44, 71, 74>::result_type x;
TD<decltype(x)> td;
// std::copy(std::begin(x.data), std::end(x.data),
// std::ostream_iterator<int64_t>(std::cout, " "));
// std::cout << std::endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment