ゆとりーなの日記

日記的な事を書いて行くと思はれる

if文なしでFizzBuzz

 が流行っているようなので(要出展)自分もやってみました。何番煎じか分からないテンプレートさんです。

#include <iostream>
#include <utility>

template <int N, int O, typename U = void>
struct fizz_buzz_impl;

template <int N>
struct int_ {};

struct stop {
  void print() const {}
};

template <int N, int O, typename T = void>
struct base {
  void next() const {
    fizz_buzz_impl<N + 1, O>().print();
  }
};

template <int N, int O>
struct base<N, O, typename std::enable_if<std::is_same<int_<N>, int_<O>>::value>::type> {
  void next() const {}
};

template <int N, int O>
struct none : base<N, O> {
  void print() const {
    std::cout << N << std::endl;
	this->next();
  }
};

template <int N, int O>
struct fizz : base<N, O> {
  void print() const {
    std::cout << "Fizz" << std::endl;
	this->next();
  }
};

template <int N, int O>
struct buzz : base<N, O> {
  void print() const {
    std::cout << "Buzz" << std::endl;
	this->next();
  }
};

template <int N, int O>
struct fizzbuzz : base<N, O> {
  void print() const {
    std::cout << "FizzBuzz" << std::endl;
	this->next();
  }
};

template <int N, int O, typename U>
struct fizz_buzz_impl : none<N, O> {};

template <int N, int O>
struct fizz_buzz_impl<N, O, typename std::enable_if<std::is_same<int_<N % 3>, int_<0>>::value && !std::is_same<int_<N % 5>, int_<0>>::value>::type> : fizz<N, O> {};

template <int N, int O>
struct fizz_buzz_impl<N, O, typename std::enable_if<std::is_same<int_<N % 5>, int_<0>>::value && !std::is_same<int_<N % 3>, int_<0>>::value>::type> : buzz<N, O> {};

template <int N, int O>
struct fizz_buzz_impl<N, O, typename std::enable_if<std::is_same<int_<N % 15>, int_<0>>::value>::type> : fizzbuzz<N, O> {};

template <int N>
struct fizz_buzz {
  void print() const {
    fizz_buzz_impl<1, N>().print();
  }
};

int main() {
  fizz_buzz<30>().print();
  return 0;
}

 長いしenable_ifとかif文みたいなもんだろって言われたら終わりですね。
 他にはこういうのも見つけました。Kazuho@Cybozu Labs: C++ テンプレートで(いまさら)FizzBuzz。こっちの方がifっぽさもないし綺麗です。