mpl::stringでコンパイル時FizzBuzz

Boostにはmpl::stringというコンパイル時文字列を表現するためのメタ関数が用意されています。
今回は、それを使ってFizzBuzzを解いてみました。
コンパイルすると結果のmpl::stringが作成されるので、実行する必要はありません。

#define BOOST_MPL_LIMIT_STRING_SIZE 64

//#include <iostream>
#include <boost/mpl/string.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/equal.hpp>
#include <shand/mpl/to_string.hpp>

namespace mpl = boost::mpl;

typedef mpl::string<'Fizz'> Fizz;
typedef mpl::string<'Buzz'> Buzz;
typedef mpl::string<'Fizz', 'Buzz'> FizzBuzz;

template <int i>
struct FizzBuzzString {
    typedef
        typename mpl::eval_if_c<
            i % 3 == 0 && i % 5 == 0,
            FizzBuzz,
            mpl::eval_if_c<
                i % 3 == 0,
                Fizz,
                mpl::eval_if_c<
                    i % 5 == 0,
                    Buzz,
                    shand::mpl::to_string<i>
                >
            >
        >::type
    value;

    typedef
        typename mpl::push_back<typename FizzBuzzString<i - 1>::type, mpl::char_<','> >::type
    next;

    typedef
        typename mpl::insert_range<
            next,
            typename mpl::end<next>::type,
            value
        >::type
    type;
};

template <>
struct FizzBuzzString<1> {
    typedef mpl::string<'1'> type;
};

typedef mpl::string<'1,2,', 'Fizz', ',4,B', 'uzz,', 'Fizz', ',7,8',
              ',Fiz', 'z,Bu', 'zz,1', '1,Fi', 'zz,1', '3,14', ',Fiz', 'zBuz', 'z'> result;

int main()
{
    BOOST_MPL_ASSERT((mpl::equal<FizzBuzzString<15>::type, result>));

//  std::cout << mpl::c_str<FizzBuzzString<15>::type>::value << std::endl;
}

mpl::stringの制限のため、1〜15のみ計算しています。


【参照】
boost::mpl::string

shand::mpl::to_string