1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
|
#include <string>
#include <iostream>
struct Nil {};
template<typename HeadT, typename TailT = Nil>
struct Cons
{
using Head = HeadT;
using Tail = TailT;
};
template<typename List>
struct IsEmpty
{
static constexpr bool value = false;
};
template<>
struct IsEmpty<Nil>
{
static constexpr bool value = true;
};
template<typename List>
struct PopFrontT
{
using Type = typename List::Tail;
};
template<>
struct PopFrontT<Nil>
{
using Type = Nil;
};
template<typename List>
using PopFront = typename PopFrontT<List>::Type;
template<typename List>
struct FrontT
{
using Type = typename List::Head;
};
template<>
struct FrontT<Nil>
{
using Type = Nil;
using Head = Nil;
};
template<typename List>
using Front = typename FrontT<List>::Type;
template<typename List,
template<typename T, typename U> class Compare,
bool = IsEmpty<List>::value>
class InsertionSortT;
template<typename List, typename Element, template<typename T, typename U> class Compare, bool isEmpty = IsEmpty<List>::value>
class InsertSortedT;
template<typename List, template<typename T, typename U> class Compare>
using InsertionSort = typename InsertionSortT<List, Compare>::Type;
// insert first element into sorted list
template<typename List, template<typename T, typename U> class Compare>
class InsertionSortT<List, Compare, false>
: public InsertSortedT< InsertionSortT<PopFront<List>, Compare>, Front<List>, Compare>
{};
// basis case (empty list is sorted)
template<typename List, template<typename T, typename U> class Compare>
class InsertionSortT<List, Compare, true>
{
public:
using Type = List;
using Head = Nil;
using Tail = Nil;
};
template<bool cond, typename TrueType, typename FalseType>
struct IfThenElseT {
using Type = TrueType;
};
template<typename TrueType, typename FalseType>
struct IfThenElseT<false, TrueType, FalseType> {
using Type = FalseType;
};
template<bool cond, typename TrueType, typename FalseType>
using IfThenElse = typename IfThenElseT<cond, TrueType, FalseType>::Type;
template<typename List, typename Element>
struct PushFrontT
{
using Type = Cons<Element, List>;
};
template<typename List, typename Element>
using PushFront = typename PushFrontT<List, Element>::Type;
// yield T when using member Type:
template<typename T>
struct IdentityT {
using Type = T;
};
template<typename T>
using Identity = typename IdentityT<T>::Type;
// recursive case
template<typename List, typename Element, template<typename T, typename U> class Compare>
class InsertSortedT<List, Element, Compare, false>
{
using NewTail = typename IfThenElseT< Compare<Element, Front<List>>::value, IdentityT<List>,
InsertSortedT<PopFront<List>, Element, Compare>>::Type;
using NewHead = IfThenElse< Compare<Element, Front<List>>::value, Element, Front<List>>;
public:
using Type = PushFront< NewTail, NewHead>;
};
// basis case
template<typename List, typename Element, template<typename T, typename U> class Compare>
class InsertSortedT<List, Element, Compare, true>
: public PushFrontT<List, Element>
{};
template<typename List, typename Element, template<typename T, typename U> class Compare, bool isEmpty>
using InsertSorted = typename InsertSortedT<List, Element, Compare, isEmpty>::Type;
template<typename T, typename U>
struct SmallerThanT
{
static constexpr bool value = sizeof(T) < sizeof(U);
};
void conslistester()
{
using ConsList = Cons<int, Cons<char, Cons<short, Cons<double>>>>;
using SortedTypes = InsertionSort<ConsList, SmallerThanT>;
using Expected = Cons<char, Cons<short, Cons<int, Cons<double>>>>;
std::cout << std::is_same<SortedTypes, Expected>::value << std::endl;
}
|