mihaild

c++ imperative templates 2.0

Nov 19th, 2014
247
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.04 KB | None | 0 0
  1. #pragma once
  2. #include <cstdlib>
  3.  
  4. template<typename...> struct Prog;
  5.  
  6. template<size_t> struct Var;
  7.  
  8. template<typename, typename> struct Sum;
  9. template<typename, typename> struct Mul;
  10. template<typename, typename> struct Mod;
  11. template<typename, typename> struct Less;
  12. template<int N> struct Int {
  13.     const static int value = N;
  14. };
  15.  
  16. template<typename, typename> struct Assign;
  17. template<typename> struct Return;
  18. template<size_t> struct Label;
  19. template<typename> struct Goto;
  20. template<typename> struct If;
  21. struct EndIf;
  22. struct Else;
  23.  
  24. template<typename...> struct List;
  25.  
  26. template<typename H, typename... T> struct List<H, T...> {
  27.     typedef H Head;
  28.     typedef List<T...> Tail;
  29. };
  30.  
  31. template<typename N, typename... P> struct PushFront;
  32. template<typename N, typename... P> struct PushFront<N, List<P...>> {
  33.     typedef List<N, P...> type;
  34. };
  35.  
  36. template<typename Op, typename Next, typename Prog, typename Log> struct Calculation;
  37.  
  38. template<typename... Args> struct Prog {
  39.     const static int value = Calculation<typename List<Args...>::Head, typename List<Args...>::Tail, List<Args...>, List<>>::value;
  40. };
  41.  
  42. template<typename T, int v> struct _Assign;
  43. template<typename Expression, typename Log> struct Eval;
  44. template<typename A, typename B, typename Next, typename Prog, typename Log> struct Calculation<Assign<A, B>, Next, Prog, Log> {
  45.     const static int value = Calculation<typename Next::Head, typename Next::Tail, Prog, typename PushFront<_Assign<A, Eval<B, Log>::value>, Log>::type>::value;
  46. };
  47.  
  48. template<typename Expression, typename Next, typename Prog, typename Log> struct Calculation<Return<Expression>, Next, Prog, Log> {
  49.     const static int value = Eval<Expression, Log>::value;
  50. };
  51.  
  52. template<size_t N, typename Next, typename Prog, typename Log> struct Calculation<Label<N>, Next, Prog, Log> {
  53.     const static int value = Calculation<typename Next::Head, typename Next::Tail, Prog, Log>::value;
  54. };
  55.  
  56. template<typename T, typename View, typename Prog, typename Log> struct CalculationGoto;
  57. template<typename T, typename Next, typename Prog, typename Log> struct Calculation<Goto<T>, Next, Prog, Log> {
  58.     const static int value = CalculationGoto<T, Prog, Prog, Log>::value;
  59. };
  60.  
  61. template<int val, typename Next, typename Prog, typename Log> struct CalculationIf;
  62. template<typename T, typename Next, typename Prog, typename Log> struct Calculation<If<T>, Next, Prog, Log> {
  63.     const static int value = CalculationIf<Eval<T, Log>::value, Next, Prog, Log>::value;
  64. };
  65.  
  66. template<typename Next, typename Prog, typename Log> struct Calculation<EndIf, Next, Prog, Log> {
  67.     const static int value = Calculation<typename Next::Head, typename Next::Tail, Prog, Log>::value;
  68. };
  69.  
  70. template<typename Op, typename Next, typename Prog, typename Log> struct CalculationNoIf;
  71. template<typename Next, typename Prog, typename Log> struct Calculation<Else, Next, Prog, Log> {
  72.     const static int value = CalculationNoIf<typename Next::Head, typename Next::Tail, Prog, Log>::value;
  73. };
  74.  
  75.  
  76. template<typename T, int v> struct _Assign {
  77.     typedef T type;
  78.     static const int value = v;
  79. };
  80.  
  81. template<typename Var, typename Log> struct ValueOf {
  82.     const static int value = ValueOf<Var, typename Log::Tail>::value;
  83. };
  84. template<typename Var, int val, typename... Args> struct ValueOf<Var, List<_Assign<Var, val>, Args...>> {
  85.     const static int value = val;
  86. };
  87. template<typename Var> struct ValueOf<Var, List<>> {
  88.     const static int value = 0;
  89. };
  90.  
  91. template<typename First, typename Second, typename Log> struct Eval<Sum<First, Second>, Log> {
  92.     const static int value = Eval<First, Log>::value + Eval<Second, Log>::value;
  93. };
  94. template<typename First, typename Second, typename Log> struct Eval<Mul<First, Second>, Log> {
  95.     const static int value = Eval<First, Log>::value * Eval<Second, Log>::value;
  96. };
  97. template<typename First, typename Second, typename Log> struct Eval<Mod<First, Second>, Log> {
  98.     const static int value = Eval<First, Log>::value % Eval<Second, Log>::value;
  99. };
  100. template<typename First, typename Second, typename Log> struct Eval<Less<First, Second>, Log> {
  101.     const static int value = Eval<First, Log>::value < Eval<Second, Log>::value;
  102. };
  103. template<int N, typename Log> struct Eval<Int<N>, Log> {
  104.     const static int value = N;
  105. };
  106. template<typename Var, typename Log> struct Eval {
  107.     const static int value = ValueOf<Var, Log>::value;
  108. };
  109.  
  110. template<typename T, typename View, typename Prog, typename Log> struct CalculationGoto {
  111.     const static int value = CalculationGoto<T, typename View::Tail, Prog, Log>::value;
  112. };
  113. template<typename T, typename... ViewTail, typename Prog, typename Log> struct CalculationGoto<T, List<T, ViewTail...>, Prog, Log> {
  114.     const static int value = Calculation<typename List<ViewTail...>::Head, typename List<ViewTail...>::Tail, Prog, Log>::value;
  115. };
  116.  
  117. template<typename Op, typename Next, typename Prog, typename Log> struct CalculationNoIf {
  118.     const static int value = CalculationNoIf<typename Next::Head, typename Next::Tail, Prog, Log>::value;
  119. };
  120. template<typename Next, typename Prog, typename Log> struct CalculationNoIf<EndIf, Next, Prog, Log> {
  121.     const static int value = Calculation<typename Next::Head, typename Next::Tail, Prog, Log>::value;
  122. };
  123. template<typename Next, typename Prog, typename Log> struct CalculationNoIf<Else, Next, Prog, Log> {
  124.     const static int value = Calculation<typename Next::Head, typename Next::Tail, Prog, Log>::value;
  125. };
  126.  
  127. template<int val, typename Next, typename Prog, typename Log> struct CalculationIf {
  128.     const static int value = Calculation<typename Next::Head, typename Next::Tail, Prog, Log>::value;
  129. };
  130. template<typename Next, typename Prog, typename Log> struct CalculationIf<0, Next, Prog, Log> {
  131.     const static int value = CalculationNoIf<typename Next::Head, typename Next::Tail, Prog, Log>::value;
  132. };
  133.  
  134.  
  135.  
  136.  
  137.  
  138.  
  139.  
  140.  
  141. template<int N, int M> struct GCD {
  142.     const static int value = Prog<
  143.         Assign<Var<0>, Int<N>>,
  144.         Assign<Var<1>, Int<M>>,
  145.         Label<0>,
  146.         If<Var<1>>,
  147.             Assign<Var<3>, Var<1>>,
  148.             Assign<Var<1>, Mod<Var<0>, Var<1>>>,
  149.             Assign<Var<0>, Var<3>>,
  150.             Goto<Label<0>>,
  151.         EndIf,
  152.         Return<Var<0>>
  153.     >::value;
  154. };
  155.  
  156. template<int N, int M> struct Max {
  157.     const static int value = Prog<
  158.         If<Less<Int<N>, Int<M>>>,
  159.             Return<Int<M>>,
  160.         Else,
  161.             Return<Int<N>>,
  162.         EndIf
  163.     >::value;
  164. };
  165.  
  166. template<int N> struct Factorial {
  167.     const static int value = Prog<
  168.         Assign<Var<0>, Int<N>>,
  169.         Assign<Var<1>, Int<1>>,
  170.         Label<0>,
  171.         If<Var<0>>,
  172.             Assign<Var<1>, Mul<Var<0>, Var<1>>>,
  173.             Assign<Var<0>, Sum<Var<0>, Int<-1>>>,
  174.             Goto<Label<0>>,
  175.         EndIf,
  176.         Return<Var<1>>
  177.     >::value;
  178. };
  179. static_assert(GCD<2, 3>::value == 1, "gcd test");
  180. static_assert(GCD<120, 18>::value == 6, "gcd test");
  181. static_assert(Max<5, 10>::value == 10, "max second");
  182. static_assert(Max<10, 5>::value == 10, "max first");
  183. static_assert(Factorial<5>::value == 120, "factorial 5");
Advertisement
Add Comment
Please, Sign In to add comment