## Fizz Buzz c++/cpp Template Meta Programming Way

### Template Meta Programming

Template metaprogramming is a set of c++ skills that the computations are done at compile time, aka the c++ compilers take our code and do computing. The c++ template is turing-complete if we do not limit the template recurring depth. We limit the template recurring depth because we do not want to let the compiling run into infinite loop.

### Fizz Buzz Problem

Fizz Buzz: Count from 1 to 100, if the number can be divided by 3, return fizz; if the number can be divided by 5, return buzz; if the number can be divided by both 3 and 5, return fizz buzz; otherwise return the number.

Program Running Output:

1 2 fizz 4 buzz fizz 7 8 fizz buzz 11 fizz 13 14 fizz-buzz 16 17 fizz 19 buzz fizz 22 23 fizz buzz 26 fizz 28 29 fizz-buzz 31 32 fizz 34 buzz fizz 37 38 fizz buzz 41 fizz 43 44 fizz-buzz 46 47 fizz 49 buzz fizz 52 53 fizz buzz 56 fizz 58 59 fizz-buzz 61 62 fizz 64 buzz fizz 67 68 fizz buzz 71 fizz 73 74 fizz-buzz 76 77 fizz 79 buzz fizz 82 83 fizz buzz 86 fizz 88 89 fizz-buzz 91 92 fizz 94 buzz fizz 97 98 fizz buzz

Fizz Buzz Problem in c++ :

### The template meta c++ code to fizz buzz problem

#### • fizz_buzz_number<number<value>>

The program stores types representing numbers from 1~100; if the number is fizz(divided by 3), stores fizz; if the number is buzz(divided by 5), stores buzz; if the number is fizz-buzz(divided by 15), stores fizz-buzz.

I make a class fizz_buzz_number, and a class number to represent if it is fizz, buzz, fizz-buzz, or number.

#### • create_tuple

create_tuple: This class takes a value of [1,100], and make a type fizz_buzz_number<number<value>>, then transfer the value-1 and the type as template parameter to next create_tuple.

When the last partial specialized template class create_tuple is called (aka when the value achieves 0), the template parameters of that create_tuple will hold all number types of fizz_buzz_number, so it can use all of them to create a tuple.

So, at last, we can take the final tuple from the class create_tuple.

• The Complete Code: fizz-bzz.cpp
```// Fizz Buzz c++/cpp
#include <iostream>
#include <tuple> // std::tuple, std::apply

template <typename T>
concept number_k = std::integral<std::decay_t<decltype(T::value)>>;
template <typename T>
concept fizz_k = number_k<T> && requires {
requires T::value%3==0;
};
template <typename T>
concept buzz_k = number_k<T> && requires {
requires T::value%5==0;
};
template <typename T>
concept fizz_buzz_k = fizz_k<T> && buzz_k<T>;

// Define number type: convert a number value to a type.
template <std::integral auto _value>
class number
{
public:
constexpr static auto value = _value;
};

// Declare class fizz_buzz_number: fizz or buzz or number
template <typename T> class fizz_buzz_number;

// Define class fizz_buzz_number and how we print them.

template <fizz_buzz_k T>
class fizz_buzz_number<T>
{
public:
friend std::ostream & operator<<(std::ostream & out,
const fizz_buzz_number<T> &)
{
return out << "fizz-buzz";
}
};
template <fizz_k T>
class fizz_buzz_number<T>
{
public:
friend std::ostream & operator<<(std::ostream & out,
const fizz_buzz_number<T> &)
{
return out << "fizz";
}
};

template <buzz_k T>
class fizz_buzz_number<T>
{
public:
friend std::ostream & operator<<(std::ostream & out,
const fizz_buzz_number<T> &)
{
return out << "buzz";
}
};

template <number_k T>
class fizz_buzz_number<T>
{
public:
friend std::ostream & operator<<(std::ostream & out,
const fizz_buzz_number<T> &)
{
return out << T::value;
}
};

// type alias
template <number_k T>
using fbn = fizz_buzz_number<T>;

// TL ... list: might be some type of fbn<number<value>>
template <std::integral auto value, typename ... TL>
class create_tuple
{
public:
/*
The trick is here:
Add the current fizz_buzz_number type to the
front of next create_tuple TL list.
The last create_tuple will hold all template parameter list,
so it will create the tuple with all number types.
*/
using tuple = typename create_tuple<value-1,
fizz_buzz_number<number<value>>, TL ...>::tuple;
};

// The last create_tuple: it will take all number types taken from
// its previous create_tuple.
template <typename ... TL>
class create_tuple<0, TL ...>
{
public:
using tuple = std::tuple<TL ...>;
};

// Get the tuple type finally.
template <std::integral auto value>
using fbn_tuple = typename create_tuple<value>::tuple;

int main()
{
// Print 1~100 fizz or buzz or number now.
std::apply(
[] (auto && ... elements) {
((std::cout << elements << ' '), ...);
std::cout << '\n';
},
fbn_tuple<100>{}
);
}
```

The code is tested running compiled by gcc and clang, with c++20 enabled.

b2 build jamfile

jamroot

```exe fizz : fizz-buzz.cpp : : <cxxstd>20 ;
``` 