Advertisement
Guest User

Lazy template fizzbuzz

a guest
Dec 4th, 2013
320
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //  
  2. //  Lazy compile-time fizzbuzz computed by C++ templates,
  3. //  without conditionals or the use of machine arithmetic.
  4. //
  5. //         -- Matt Noonan (mnoonan@grammatech.com)
  6.  
  7. #include <iostream>
  8.  
  9. using namespace std;
  10.  
  11. //
  12. //  The natural numbers: Nat = Zero | Succ Nat
  13. //
  14.  
  15. template <typename n>
  16. struct Succ
  17. {
  18.   typedef Succ eval;
  19.   static const unsigned int toInt = 1 + n::toInt;
  20.   static void print(ostream & o) { o << toInt; }
  21. };
  22.  
  23. struct Zero
  24. {
  25.   typedef Zero eval;
  26.   static const unsigned int toInt = 0;
  27.   static void print(ostream & o) { o << toInt; }
  28. };
  29.  
  30. //
  31. //  Arithmetic operators
  32. //    Plus Zero n = n
  33. //    Plus Succ(n) m = Plus n Succ(m)
  34. //    Times Zero n = Zero
  35. //    Times Succ(n) m = Plus m (Times n m)
  36. //
  37.  
  38. template <typename a, typename b>
  39. struct Plus
  40. {
  41.   typedef typename Plus<typename a::eval,
  42.             typename b::eval>::eval eval;
  43. };
  44.  
  45. template <typename M>
  46. struct Plus <Zero, M>
  47. { typedef typename M::eval eval; };
  48.  
  49. template <typename N, typename M>
  50. struct Plus <Succ<N>, M>
  51. { typedef typename Plus<N, Succ<M> >::eval eval; };
  52.  
  53. template <typename a, typename b>
  54. struct Times
  55. {
  56.   typedef typename Times<typename a::eval,
  57.              typename b::eval>::eval eval;
  58. };
  59.  
  60. template <typename M>
  61. struct Times <Zero, M>
  62. { typedef Zero::eval eval; };
  63.  
  64. template <typename N, typename M>
  65. struct Times <Succ<N>, M>
  66. { typedef typename Plus<M,
  67.             typename Times<N,M>::eval
  68.             >::eval eval; };
  69.  
  70. //
  71. //  Lists
  72. //
  73.  
  74. struct Nil
  75. {
  76.   typedef Nil eval;
  77.   static void print(ostream & o) { }
  78. };
  79.  
  80. template <typename x, typename xs>
  81. struct Cons
  82. {
  83.   typedef Cons eval;
  84.   static void print(ostream & o) {
  85.     x::eval::print(o); o << endl; xs::eval::print(o);
  86.   }
  87. };
  88.  
  89. //
  90. //  Take the first n elements of a list
  91. //
  92.  
  93. template <typename, typename> struct Take;
  94.  
  95. template <typename _> struct Take<Zero,_>
  96. { typedef Nil eval; };
  97.  
  98. template <typename n, typename x, typename xs>
  99. struct Take<Succ<n>, Cons<x,xs> >
  100. {
  101.   typedef Cons<x, Take<n, xs> > eval;
  102. };
  103.  
  104. template <typename a, typename b>
  105. struct Take
  106. {
  107.   typedef typename Take<typename a::eval,
  108.             typename b::eval>::eval eval;
  109. };
  110.  
  111. //
  112. //  Iterate f x0 makes the infinite list
  113. //  x0, f(x0), f(f(x0)), ...
  114. //
  115.  
  116. template <template<typename> class f, typename x0> struct Iterate
  117. {
  118.   typedef Cons<x0, Iterate<f, f<x0> > > eval;
  119. };
  120.  
  121. //
  122. //  Map a function over a list
  123. //
  124.  
  125. template <template<typename> class a, typename b> struct Map
  126. { typedef typename Map<a,
  127.                typename b::eval>::eval eval;
  128. };
  129.  
  130. template <template<typename> class f>
  131. struct Map<f, Nil>
  132. { typedef Nil eval; };
  133.  
  134. template <template<typename> class f, typename x, typename xs>
  135. struct Map<f, Cons<x,xs> >
  136. {
  137.   typedef Cons<f<x>, Map<f,xs> > eval;
  138. };
  139.  
  140. //
  141. //  Some useful things for making fizzes and buzzes
  142. //
  143.  
  144. struct Fizz
  145. { static void print(ostream & o) { o << "Fizz"; } };
  146.  
  147. struct Buzz
  148. { static void print(ostream & o) { o << "Buzz"; } };
  149.  
  150. struct FizzBuzz
  151. { static void print(ostream & o) { o << "FizzBuzz"; } };
  152.  
  153. //
  154. //  Some useful numbers
  155. //
  156.  
  157. typedef Succ<Zero> One;
  158. typedef Succ<One> Two;
  159. typedef Succ<Two> Three;
  160. typedef Plus<Two, Three> Five;
  161. typedef Times<Two, Five> Ten;
  162. typedef Times<Three, Five> Fifteen;
  163. typedef Times<Ten, Ten> OneHundred;
  164.  
  165. //
  166. //  Booleans
  167. //
  168.  
  169. struct True {};
  170. struct False {};
  171.  
  172. //
  173. //  If/then/else
  174. //
  175.  
  176. template <typename p, typename t, typename f>
  177. struct If
  178. {
  179.   typedef typename If<typename p::eval, t, f>::eval eval;
  180.   static void print(ostream & o) { eval::print(o); }
  181. };
  182.  
  183. template <typename t, typename _>
  184. struct If<True, t, _>
  185. {
  186.   typedef t eval;
  187. };
  188.  
  189. template <typename _, typename f>
  190. struct If<False, _, f>
  191. { typedef f eval; };
  192.      
  193. //
  194. //  Testing if x divides y
  195. //
  196.  
  197. template <typename a, typename b, typename c>
  198. struct _Divides
  199. {
  200.   typedef typename _Divides<typename a::eval,
  201.                 typename b::eval,
  202.                 typename c::eval>::eval eval;
  203. };
  204.  
  205. template <typename _, typename __>
  206. struct _Divides<_, __, Zero> { typedef False eval; };
  207.  
  208. template <typename a>
  209. struct _Divides<a, Zero, Zero> { typedef True eval; };
  210.  
  211. template <typename a, typename b>
  212. struct _Divides<a, Zero, b>
  213. {
  214.   typedef typename _Divides<a, a, b>::eval eval;
  215. };
  216.  
  217. template <typename _, typename n, typename m>
  218. struct _Divides<_, Succ<n>, Succ<m> >
  219. {
  220.   typedef typename _Divides<_, n, m>::eval eval;
  221. };
  222.  
  223. template <typename a, typename b>
  224. struct Divides
  225. {
  226.   typedef typename _Divides<a, a, b>::eval eval;
  227. };
  228.  
  229. //
  230. //  "Otherwise" sugar
  231. //
  232.  
  233. template <typename a>
  234. struct Otherwise
  235. {
  236.   typedef typename a::eval eval;
  237.   static void print(ostream & o) { a::eval::print(o); }
  238. };
  239.  
  240. //
  241. //  Convert a number to fizzes, buzzes as appropriate
  242. //
  243.  
  244. template <typename n>
  245. struct toFizzBuzz
  246. {
  247.   typedef typename
  248.     If< Divides<Fifteen, n>, FizzBuzz,
  249.     If< Divides<   Five, n>,     Buzz,
  250.     If< Divides<  Three, n>,     Fizz,
  251.     Otherwise<                   n
  252.     > > > >::eval eval;
  253. };
  254.  
  255. int main(void)
  256. {
  257.   // Make all of the natural numbers
  258.   typedef Iterate<Succ, One> Naturals;
  259.  
  260.   // Apply fizzbuzz rules to every natural number
  261.   typedef Map<toFizzBuzz, Naturals> FizzBuzzedNaturals;
  262.  
  263.   // Print out the first hundred fizzbuzzed numbers
  264.   Take<OneHundred, FizzBuzzedNaturals>::eval::print(cout);
  265.  
  266.   return 0;
  267. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement