Skip to content

Instantly share code, notes, and snippets.

@archibald1418
Created July 14, 2022 00:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save archibald1418/972b5b2f88b3f7ac2bee8e186fe2d395 to your computer and use it in GitHub Desktop.
Save archibald1418/972b5b2f88b3f7ac2bee8e186fe2d395 to your computer and use it in GitHub Desktop.
Fizzbuzz on templates without <type_traits>
#include <iostream>
// Truthiness
struct true_type{static const bool value = true;};
struct false_type{ static const bool value = false;};
// Pick type based on bool value
template <bool B, typename T, typename U>
struct conditional{
typedef T type;
};
template <typename T, typename U>
struct conditional<false, T, U>{
typedef U type;
};
// Compare two types
template <typename T, typename U>
struct is_same : public false_type{};
template <typename T>
struct is_same<T, T> : public true_type{};
// Division predicate
template <int a, int b>
struct divides{
static const bool value = (a % b == 0);
};
// Type traits
template <typename T, int N = 0>
struct fizzbuzz_traits{
typedef T type;
static const int value = N;
};
template <>
struct fizzbuzz_traits<char*, 0>{
typedef char* type;
};
// fizzbuzz type initializers
template <bool A, bool B>
struct fizzbuzz{};
template <> struct fizzbuzz<true, false> : public fizzbuzz_traits<char*> {
static const char* value;
};
typedef fizzbuzz<true, false> fizz_type;
const char* fizz_type::value = "fizz"; // pre-C++11 compiler requires out-of-line initialization for const char*
template <> struct fizzbuzz<true, true> : public fizzbuzz_traits<char*> {
static const char* value;
};
typedef fizzbuzz<true, true> fizzbuzz_type;
const char *fizzbuzz_type::value = "fizzbuzz";
template <> struct fizzbuzz<false, true> : public fizzbuzz_traits<char*> {
static const char* value;
};
typedef fizzbuzz<false, true> buzz_type;
const char *buzz_type::value = "buzz";
template <> struct fizzbuzz<false, false> : fizzbuzz_traits<void>{};
// FizzBuzz solver
template <int N>
class FizzBuzz{
private:
struct is_divisible : public true_type{
struct by3 : public divides<N, 3>{};
struct by5 : public divides<N, 5>{};
};
public:
typedef fizzbuzz< is_divisible::by3::value, is_divisible::by5::value > solution_type;
// stores string or 'false'
typedef fizzbuzz_traits<int, N> non_divisible_type;
// stores number
typedef typename conditional< !is_same<void, typename solution_type::type>::value,
solution_type,
non_divisible_type>::type print_type;
// stores value to print
};
// Looping from N to M
template <int N, int M>
struct static_for{
static void value(){
std::cout << FizzBuzz<N>::print_type::value << std::endl;
static_for<N + 1, M>::value();
}
};
template <>
struct static_for<101, 100>
{
static void value(){};
};
int main(){
static_for<1, 100>::value();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment