fork download
  1. int main() { return 0; }
  2.  
  3. #include <iostream>
  4.  
  5. #pragma mark Definition: Boolean
  6.  
  7. struct True { };
  8. struct False { };
  9.  
  10. #pragma mark Definition: Equality
  11.  
  12. namespace {
  13. template <typename, typename>
  14. struct eq_impl { using type = False; };
  15.  
  16. template <typename A>
  17. struct eq_impl<A, A> { using type = True; };
  18. };
  19.  
  20. template <typename A, typename B>
  21. using Equal = typename eq_impl<A, B>::type;
  22.  
  23. #pragma mark Definition: Natural Number
  24.  
  25. struct Zero {};
  26. template <typename>
  27. struct S {};
  28.  
  29. template <typename>
  30. struct Eval;
  31.  
  32. template <>
  33. struct Eval<Zero> {
  34. static constexpr int value = 0;
  35. };
  36. template <typename Num>
  37. struct Eval<S<Num>> {
  38. static constexpr int value = 1 + Eval<Num>::value;
  39. };
  40.  
  41. std::ostream &operator<<(std::ostream &os, const Zero &) {
  42. os << Eval<Zero>::value;
  43. return os;
  44. }
  45.  
  46. template <typename Num>
  47. std::ostream &operator<<(std::ostream &os, const S<Num> &) {
  48. os << Eval<S<Num>>::value;
  49. return os;
  50. }
  51.  
  52. #pragma mark Definition: If
  53.  
  54. namespace {
  55. template <typename Condition, typename Then, typename Else>
  56. struct if_impl;
  57.  
  58. template <typename Then, typename Else>
  59. struct if_impl<True, Then, Else> {
  60. using type = Then;
  61. };
  62.  
  63. template <typename Then, typename Else>
  64. struct if_impl<False, Then, Else> {
  65. using type = Else;
  66. };
  67. };
  68.  
  69. template <typename Condition, typename Then, typename Else>
  70. using If = typename if_impl<Condition, Then, Else>::type;
  71.  
  72. #pragma mark Definition: Or
  73.  
  74. namespace {
  75. template <typename, typename>
  76. struct or_impl {
  77. using type = True;
  78. };
  79.  
  80. template <>
  81. struct or_impl<False, False> {
  82. using type = False;
  83. };
  84. };
  85.  
  86. template <typename P, typename Q>
  87. using Or = typename or_impl<P, Q>::type;
  88.  
  89. #pragma mark Utility
  90.  
  91. namespace {
  92. template <int n>
  93. struct make_num_impl {
  94. using type = S<typename make_num_impl<n - 1>::type>;
  95. };
  96.  
  97. template <>
  98. struct make_num_impl<0> {
  99. using type = Zero;
  100. };
  101. };
  102.  
  103. template <int n>
  104. using MakeNum = typename make_num_impl<n>::type;
  105.  
  106. struct Stop {};
  107.  
  108. struct Nothing {};
  109. std::ostream &operator<<(std::ostream &os, const Nothing *) { return os; };
  110.  
  111. struct LineBreak { LineBreak() { std::cout << std::endl; } };
  112.  
  113. template <typename X, typename Y, typename T>
  114. using Enable = If<Equal<X, Y>, Stop, T>;
  115.  
  116. #pragma mark Implementation of Fizz / Buzz
  117.  
  118. #define DefineFizzBuzz(Name, ...)\
  119. template <typename Num, typename C = Zero> struct Name;\
  120. template <typename Num, typename C> struct Name<S<Num>, C> : public Name<Num, If<Equal<C, __VA_ARGS__>, Zero, S<C>>> {};\
  121. template <typename C> struct Name<Zero, C> { using is_enable = Equal<C, Zero>;\
  122.   Name() { std::cout << static_cast<If<is_enable, Name, Nothing> *>(nullptr); };\
  123. };\
  124. template <typename Num, typename C> std::ostream &operator<<(std::ostream &os, const Name<Num, C> *) {\
  125.   os << #Name;\
  126.   return os;\
  127. };
  128.  
  129. DefineFizzBuzz(Fizz, S<S<Zero>>);
  130. DefineFizzBuzz(Buzz, S<S<S<S<Zero>>>>);
  131.  
  132. #pragma mark Implementation of Number
  133.  
  134. template <typename> struct number_impl;
  135.  
  136. template <typename Num>
  137. struct number_impl {
  138. number_impl() { std::cout << Num(); }
  139. };
  140.  
  141. template <typename Num>
  142. using Number = If<Or<typename Fizz<Num>::is_enable, typename Buzz<Num>::is_enable>, Nothing, number_impl<Num>>;
  143.  
  144. #pragma mark FizzBuzz Composition
  145.  
  146. template <typename Num, typename Max>
  147. struct fizz_buzz_impl : public
  148. Fizz<Num>
  149. , Buzz<Num>
  150. , Number<Num>
  151. , LineBreak
  152. , Enable<Num, Max, fizz_buzz_impl<S<Num>, Max>> { };
  153.  
  154. template <int n>
  155. using FizzBuzz = fizz_buzz_impl<S<Zero>, MakeNum<n>>;
  156.  
  157. FizzBuzz<20> fizzbuzz;
Success #stdin #stdout 0s 3100KB
stdin
Standard input is empty
stdout
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz