ユーザ定義リテラルを使った FizzBuzz

まぁ処理自体は、Boost.MPL で行っているんですが。
整数は template で受け取る事が出来るので、Boost.MPL を使用してコンパイル時に処理することが出来ます。

[ソース]

#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 で行っています。

[コンパイラ]

  • g++ (GCC) 4.7.0 20111029 (experimental)