ユーザ定義リテラルを使った FizzBuzz
まぁ処理自体は、Boost.MPL で行っているんですが。
整数は template
[ソース]
#include <iostream> #include <type_traits> #include <string> #include <utility> #include <boost/mpl/string.hpp> #include <boost/mpl/eval_if.hpp> namespace mpl = boost::mpl; // mpl::c_str には value_type が無いので定義 template<typename Seq> struct c_str : mpl::c_str<Seq>{ typedef c_str type; typedef char const* value_type; }; template<typename N> struct FizzBuzz : mpl::eval_if<mpl::bool_<N::value % 15 == 0>, c_str<mpl::string<'Fizz', 'Buzz'>>, mpl::eval_if<mpl::bool_<N::value % 3 == 0>, c_str<mpl::string<'Fizz'>>, mpl::eval_if<mpl::bool_<N::value % 5 == 0>, c_str<mpl::string<'Buzz'>>, N>>>::type {}; template<int acc, char ...cs> struct atoi_impl : std::integral_constant<int, acc>{}; template<int acc, char c, char ...cs> struct atoi_impl<acc, c, cs...> : atoi_impl<(acc * 10) + (c - '0'), cs...>{}; template<char ...cs> struct atoi : atoi_impl<0, cs...>{}; template<char ...cs> constexpr typename FizzBuzz<atoi<cs...>>::value_type operator "" _FizzBuzz(){ return FizzBuzz<atoi<cs...>>::value; } int main(){ std::cout << 1_FizzBuzz << ", "; std::cout << 2_FizzBuzz << ", "; std::cout << 3_FizzBuzz << ", "; // 以下、Boost.PP で展開 #define FIZZ_BUZZ_DISP(z, n, text) std::cout << BOOST_PP_CAT(n, _FizzBuzz) << ", "; BOOST_PP_REPEAT_FROM_TO(3, 50, FIZZ_BUZZ_DISP, ~) return 0; }
[出力]
1, 2, Fizz, 4, 4, Buzz, Fizz, 7, 8, Fizz, Buzz, 11, Fizz, 13, 14, FizzBuzz, 16, 17, Fizz, 19, Buzz, Fizz, 22, 23, Fizz, Buzz, 26, Fizz, 28, 29, FizzBuzz, 31, 32, Fizz, 34, Buzz, Fizz, 37, 38, Fizz, Buzz, 41, Fizz, 43, 44, FizzBuzz, 46, 47, Fizz, 49,
1〜n までに 手打ちで書くのは手間なので、展開は Boost.PP で行っています。