Advertisement
Guest User

CppTemplateMetaprog

a guest
Feb 18th, 2014
421
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.83 KB | None | 0 0
  1. #include <iostream>
  2.  
  3. using namespace std;
  4.  
  5.  
  6. namespace tcalc {
  7.  
  8. template< typename T, T v = T() >
  9. struct Value
  10. {
  11.     enum { val = v };
  12.     typedef T value_type;
  13. };
  14.  
  15. template< typename T, T v >
  16. struct Negate
  17. {
  18.     enum { val = -v };
  19. };
  20.  
  21. // comparision
  22. template< class V1, class V2>
  23. struct Less
  24. {
  25.     enum { val = V1::val < V2::val };
  26. };
  27.  
  28. template< class V1, class V2>
  29. struct LessOrEqual
  30. {
  31.     enum { val = V1::val <= V2::val };
  32. };
  33.  
  34. template< class V1, class V2 >
  35. struct Equal
  36. {
  37.     enum { val = V1::val == V2::val };
  38. };
  39.  
  40. template< class V1, class V2 >
  41. struct Greater
  42. {
  43.     enum { val = V1::val > V2::val };
  44. };
  45.  
  46. template< class V1, class V2 >
  47. struct GreaterOrEqual
  48. {
  49.     enum { val = V1::val >= V2::val };
  50. };
  51.  
  52. template< class V1, class V2 >
  53. class Min
  54. {
  55.     template< class Vi1, class Vi2, int lesser >
  56.     struct MinR;
  57.  
  58.     template< class Vi1, class Vi2 >
  59.     struct MinR< Vi1, Vi2, 1 >
  60.     {
  61.         typedef Vi1 NextType;
  62.     };
  63.  
  64.     template< class Vi1, class Vi2 >
  65.     struct MinR< Vi1, Vi2, 0 >
  66.     {
  67.         typedef Vi2 NextType;
  68.     };
  69.  
  70. public:
  71.     typedef typename MinR< V1, V2, Less< V1, V2 >::val >::NextType NextType;
  72. };
  73.  
  74. template< class V1, class V2 >
  75. class Max
  76. {
  77.     template< class Vi1, class Vi2, int lesser >
  78.     struct MaxR;
  79.  
  80.     template< class Vi1, class Vi2 >
  81.     struct MaxR< Vi1, Vi2, 1 >
  82.     {
  83.         typedef Vi2 NextType;
  84.     };
  85.  
  86.     template< class Vi1, class Vi2 >
  87.     struct MaxR< Vi1, Vi2, 0 >
  88.     {
  89.         typedef Vi1 NextType;
  90.     };
  91.  
  92. public:
  93.     typedef typename MaxR< V1, V2, Less< V1, V2 >::val >::NextType NextType;
  94. };
  95.  
  96. // arithmetic
  97. template< class V1, class V2 >
  98. struct Add
  99. {
  100.     enum { val = V1::val + V2::val };
  101. };
  102.  
  103. template< class V1, class V2 >
  104. struct Sub
  105. {
  106.     enum { val = V1::val - V2::val };
  107. };
  108.  
  109. template< class V1, class V2 >
  110. struct Mul
  111. {
  112.     enum { val = V1::val * V2::val };
  113. };
  114.  
  115. template< class V1, class V2 >
  116. struct Div
  117. {
  118.     enum { val = V1::val / V2::val };
  119. };
  120.  
  121. template< class V, unsigned p >
  122. struct Power
  123. {
  124.     enum { val = Power< V, p - 1 >::val * V::val };
  125. };
  126.  
  127. template< class V >
  128. struct Power< V, 1 >
  129. {
  130.     enum { val = V::val };
  131. };
  132.  
  133. template< class V >
  134. struct Power< V, 0 >
  135. {
  136.     enum { val = 1 };
  137. };
  138.  
  139. // special-purpose
  140. template< unsigned v >
  141. struct Factorial
  142. {
  143.     enum { val = Factorial< v - 1 >::val * v };
  144. };
  145.  
  146. template<>
  147. struct Factorial<0>
  148. {
  149.     enum { val = 1 };
  150. };
  151.  
  152. ////////////////////////////////
  153. namespace container {
  154.  
  155. namespace list {
  156.  
  157. struct NullItem
  158. {
  159.     enum { val };
  160.     static void Print() { cout << endl; }
  161. };
  162.  
  163. template< typename V, typename L >
  164. struct List
  165. {
  166.     enum { val = V::val };
  167.     typedef V value_type;
  168.  
  169.     static void Print()
  170.     {
  171.         cout << val << ", ";
  172.         L::Print();
  173.     }
  174. };
  175.  
  176. template< class List > struct ListLength;
  177.  
  178. template<>
  179. struct ListLength< NullItem >
  180. {
  181.     enum { val = 0 };
  182. };
  183.  
  184. template< class V, class L >
  185. struct ListLength< List< V, L > >
  186. {
  187.     enum { val = 1 + ListLength<L>::val };
  188. };
  189.  
  190. template< class List > struct Next;
  191.  
  192. template< class V, class L >
  193. struct Next< List< V, L > >
  194. {
  195.     typedef L NextType;
  196. };
  197.  
  198. template< class L, int step >
  199. class Advance
  200. {
  201.     typedef typename Next< L >::NextType Forward;
  202. public:
  203.     typedef typename Advance< Forward, step - 1 >::NextType NextType;
  204. };
  205.  
  206. template< class L >
  207. class Advance< L, 1 >
  208. {
  209. public:
  210.     typedef typename Next< L >::NextType NextType;
  211. };
  212.  
  213. template< class L >
  214. class Advance< L, 0 >
  215. {
  216. public:
  217.     typedef L NextType;
  218. };
  219.  
  220. template< class L, int length = ListLength< L >::val >
  221. class Reverse
  222. {
  223.     typedef typename Advance< L, length - 1 >::NextType::value_type Last;
  224. public:
  225.     typedef List< Last, typename Reverse< L, length - 1 >::NextType > NextType;
  226. };
  227.  
  228. template< class L >
  229. class Reverse< L, 1 >
  230. {
  231.     typedef typename L::value_type First;
  232. public:
  233.     typedef List< First, NullItem > NextType;
  234. };
  235.  
  236. template< class L, int length = ListLength< L >::val >
  237. class PopBack
  238. {
  239.     typedef typename Next< L >::NextType Remaining;
  240. public:
  241.     typedef List< typename L::value_type, typename PopBack< Remaining, length - 1 >::NextType > NextType;
  242. };
  243.  
  244. template< class L>
  245. class PopBack< L, 2 >
  246. {
  247. public:
  248.     typedef List< typename L::value_type, NullItem > NextType;
  249. };
  250.  
  251. template< class L >
  252. struct PopFront
  253. {
  254.     typedef typename Next< L >::NextType NextType;
  255. };
  256.  
  257. template< class V, class L >
  258. class PushBack
  259. {
  260.     typedef typename Reverse< L >::NextType Reversed;
  261.     typedef List< V, Reversed > ReversedA;
  262. public:
  263.     typedef typename Reverse< ReversedA >::NextType NextType;
  264. };
  265.  
  266. template< class L1, class L2 >
  267. class Merge
  268. {
  269.     typedef typename PushBack< typename L2::value_type, L1 >::NextType MergedWithFirst;
  270.     typedef typename Next< L2 >::NextType L2_NextType;
  271. public:
  272.     typedef typename Merge< MergedWithFirst, L2_NextType >::NextType NextType;
  273. };
  274.  
  275. template< class L1 >
  276. class Merge< L1, NullItem >
  277. {
  278. public:
  279.     typedef L1 NextType;
  280. };
  281.  
  282. template< class L, unsigned n, unsigned i = 0 >
  283. class First
  284. {
  285.     typedef List< typename L::value_type, NullItem > Trivial;
  286.  
  287.     template< class Li, unsigned ni, class Ri, unsigned ii >
  288.     class FirstR
  289.     {
  290.         enum { index = ni - ii };
  291.         typedef typename PushBack< typename Advance< Li, index >::NextType, Ri >::NextType Ls;
  292.     public:
  293.         typedef typename FirstR< Li, ni, Ls, ii - 1 >::NextType NextType;
  294.     };
  295.  
  296.     template< class Li, unsigned ni, class Ri >
  297.     class FirstR< Li, ni, Ri, 0 >
  298.     {
  299.     public:
  300.         typedef Ri NextType;
  301.     };
  302.  
  303. public:
  304.     typedef typename FirstR< L, n, Trivial, n - 1 >::NextType NextType;
  305. };
  306.  
  307. template< class L, class Item, unsigned index, unsigned length = ListLength< L >::val >
  308. class InsertAt
  309. {
  310.     typedef typename First<L, index>::NextType L1;
  311.     typedef typename Advance<L, index>::NextType L2;
  312.     typedef typename PushBack< Item, L1 >::NextType L1PlusItem;
  313. public:
  314.     typedef typename Merge< L1PlusItem, L2 >::NextType NextType;
  315. };
  316.  
  317. template< class L, class Item, unsigned index >
  318. class InsertAt< L, Item, index, index >
  319. {
  320. public:
  321.     typedef typename PushBack< Item, L >::NextType NextType;
  322. };
  323.  
  324. template< class L, class Item, unsigned length >
  325. class InsertAt< L, Item, 0, length >
  326. {
  327. public:
  328.     typedef List< Item, L > NextType;
  329. };
  330.  
  331. template< class L, unsigned index >
  332. class EraseByIndex
  333. {
  334.     typedef typename First<L, index>::NextType L1;
  335.     typedef typename Advance<L, index + 1>::NextType L2;
  336. public:
  337.     typedef typename Merge< L1, L2 >::NextType NextType;
  338. };
  339.  
  340. template< class L >
  341. class EraseByIndex< L, 0 >
  342. {
  343. public:
  344.     typedef typename Next<L>::NextType NextType;
  345. };
  346.  
  347. template< class Ls, class it >
  348. class Search
  349. {
  350.     template< class L, class item, unsigned i, int eq >
  351.     class SearchR;
  352.  
  353.     template< class L, class item, unsigned i >
  354.     class SearchR< L, item, i, 1 >
  355.     {
  356.     public:
  357.         enum { val = i };
  358.     };
  359.  
  360.     template< class item, unsigned i >
  361.     class SearchR< NullItem, item, i, 1 >
  362.     {
  363.     public:
  364.         enum { val = i };
  365.     };
  366.  
  367.     template< class item, unsigned i >
  368.     class SearchR< NullItem, item, i, 0 >
  369.     {
  370.     public:
  371.         enum { val = -1 };
  372.     };
  373.  
  374.     template< class L, class item, unsigned i >
  375.     class SearchR< L, item, i, 0 >
  376.     {
  377.         typedef typename Next<L>::NextType NextType;
  378.     public:
  379.         enum { val = SearchR< NextType, item, i + 1, Equal< NextType, item >::val >::val };
  380.     };
  381.  
  382. public:
  383.     enum { val = SearchR< Ls, it, 0, Equal< Ls, it >::val >::val };
  384. };
  385.  
  386. template< class L, class Min = L >
  387. class FindMinimum
  388. {
  389.     typedef typename Next<L>::NextType Forward;
  390.     typedef typename tcalc::Min< L, Min >::NextType CurrentMin;
  391. public:
  392.     typedef typename FindMinimum< Forward, CurrentMin >::NextType NextType;
  393. };
  394.  
  395. template< class Min >
  396. class FindMinimum< NullItem, Min >
  397. {
  398. public:
  399.     typedef Min NextType;
  400. };
  401.  
  402. template< class Ls, class it >
  403. class LowerBound
  404. {
  405.     template< class L, class item, unsigned i, int eq >
  406.     class LowerR;
  407.  
  408.     template< class L, class item, unsigned i >
  409.     class LowerR< L, item, i, 1 >
  410.     {
  411.     public:
  412.         enum { val = i };
  413.     };
  414.  
  415.     template< class item, unsigned i >
  416.     class LowerR< NullItem, item, i, 1 >
  417.     {
  418.     public:
  419.         enum { val = i };
  420.     };
  421.  
  422.     template< class item, unsigned i >
  423.     class LowerR< NullItem, item, i, 0 >
  424.     {
  425.     public:
  426.         enum { val = i };
  427.     };
  428.  
  429.     template< class L, class item, unsigned i >
  430.     class LowerR< L, item, i, 0 >
  431.     {
  432.         typedef typename Next<L>::NextType NextType;
  433.     public:
  434.         enum { val = LowerR< NextType, item, i + 1, GreaterOrEqual< NextType, item >::val >::val };
  435.     };
  436.  
  437. public:
  438.     enum { val = LowerR< Ls, it, 0, GreaterOrEqual< Ls, it >::val >::val };
  439. };
  440.  
  441.  
  442. template< class L1, class L2 >
  443. class MergeSorted
  444. {
  445.     typedef typename FindMinimum< L2 >::NextType E;
  446.     typedef Search< L2, E > Found;
  447.     typedef typename EraseByIndex< L2, Found::val >::NextType L2MinusMin;
  448.  
  449.     typedef LowerBound< L1, E > LB;
  450.     typedef typename InsertAt< L1, E, LB::val >::NextType L1PlusMin;
  451. public:
  452.     typedef typename MergeSorted< L1PlusMin, L2MinusMin >::NextType NextType;
  453. };
  454.  
  455. template< class L1 >
  456. class MergeSorted< L1, NullItem >
  457. {
  458. public:
  459.     typedef L1 NextType;
  460. };
  461.  
  462. template< class L, unsigned length = ListLength< L >::val >
  463. class MergeSort
  464. {
  465.     typedef ListLength< L > Length;
  466.     typedef typename First< L, Length::val / 2 >::NextType L1;
  467.     typedef typename Advance< L, Length::val / 2 >::NextType L2;
  468.  
  469.     typedef typename MergeSort< L1 >::NextType L1_sorted;
  470.     typedef typename MergeSort< L2 >::NextType L2_sorted;
  471. public:
  472.     typedef typename MergeSorted< L1_sorted, L2_sorted >::NextType NextType;
  473. };
  474.  
  475. template< class L >
  476. class MergeSort< L, 2 >
  477. {
  478.     typedef L E1;
  479.     typedef typename Next<L>::NextType E2;
  480.  
  481.     typedef typename Min<E1, E2>::NextType R1;
  482.     typedef typename Max<E1, E2>::NextType R2;
  483. public:
  484.     typedef List< Value< int, R1::val >, List< Value< int, R2::val >, NullItem > > NextType; // TODO: int
  485. };
  486.  
  487. template< class L >
  488. class MergeSort< L, 1 >
  489. {
  490. public:
  491.     typedef L NextType;
  492. };
  493.  
  494. } // namespace list
  495.  
  496. } // namespace container
  497.  
  498. } // namespace tcalc
  499.  
  500.  
  501. int main()
  502. {
  503.     using namespace tcalc;
  504.     using namespace tcalc::container::list;
  505.     const int v = Add< Value<int, 3>, Value<int, 42> >::val;
  506.     const int ret = Power< Div< Value<int, 42>, Value<int, 21> >, Value<int, 8>::val >::val;
  507.  
  508.     typedef List< Value<int, 3>, List< Value<int, 2>, List< Value<int, 1>, NullItem > > > FunnyList;
  509.     typedef List< Value<int, 5>, List< Value<int, 4>, List< Value<int, 6>, NullItem > > > FunnyList2;
  510.  
  511.     typedef typename Merge< FunnyList, FunnyList2 >::NextType MergedList;
  512.     typedef typename MergeSort< MergedList >::NextType Sorted;
  513.     Sorted::Print();
  514.  
  515.     return 0;
  516. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement