Boost.MPL で FibBuzz

ついカッとなってやった。反省はしていない。

[ソース]

#define BOOST_MPL_LIMIT_VECTOR_SIZE 40
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/long.hpp>
#include <boost/mpl/equal_to.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/minus.hpp>
#include <boost/mpl/modulus.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/transform_view.hpp>
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/print.hpp>
#include <boost/mpl/back_inserter.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/copy.hpp>

namespace mpl = boost::mpl;


template<typename N>
struct fibonacci;

template<typename N>
struct fibonacci
    : mpl::eval_if<
        mpl::equal_to<N, mpl::long_<0> >,
        mpl::long_<0>,
        mpl::if_<
            mpl::equal_to<N, mpl::long_<1> >,
            mpl::long_<1>,
            mpl::plus<
                fibonacci<typename mpl::minus<N, mpl::long_<1> >::type>,
                fibonacci<typename mpl::minus<N, mpl::long_<2> >::type>
            >
        >
    >::type
{};

struct Fizz : mpl::identity<Fizz>{};
struct Buzz : mpl::identity<Buzz>{};
struct FizzBuzz : mpl::identity<FizzBuzz>{};

template<typename N>
struct to_fissbuzz
    : mpl::eval_if<
        mpl::equal_to<mpl::modulus<N, mpl::long_<15> >, mpl::long_<0> >,
        FizzBuzz,
        mpl::eval_if<
            mpl::equal_to<mpl::modulus<N, mpl::long_<3> >, mpl::long_<0> >,
            Fizz,
            mpl::eval_if<
                mpl::equal_to<mpl::modulus<N, mpl::long_<5> >, mpl::long_<0> >,
                Buzz,
                N
            >
        >
    >::type
{};


typedef mpl::range_c<long, 1, 41> seq;

typedef mpl::copy<
    mpl::transform_view<
        mpl::transform_view<
            seq,
            fibonacci<mpl::_1>
        >::type,
        to_fissbuzz<mpl::_1>
    >,
    mpl::back_inserter<mpl::vector<> >
> result;

typedef mpl::print<result::type>::type disp;


int main(){}

[出力]

|| main.cpp
|| D:/compiletime/main.cpp : warning C4819: ファイルは、現在のコード ページ (932) で表示できない文字を含んでいます。データの損失を防ぐために、ファイルを Unicode 形式で保存してください。
\boost\boost_1_47_0\boost\mpl\print.hpp|51 warning 4308| 負の整数定数が符号なしの型に変換されました。
main.cpp|94| コンパイルされたクラスの テンプレート のインスタンス化 'boost::mpl::print<T>' の参照を確認してください
||         with
||         [
||             T=boost::mpl::vector40<boost::mpl::long_<1>,boost::mpl::integral_c<long,1>,boost::mpl::integral_c<long,2>,Fizz,Buzz,boost::mpl::integral_c<long,8>,boost::mpl::integral_c<long,13>,Fizz,boost::mpl::integral_c<long,34>,Buzz,boost::mpl::integral_c<long,89>,Fizz,boost::mpl::integral_c<long,233>,boost::mpl::integral_c<long,377>,Buzz,Fizz,boost::mpl::integral_c<long,1597>,boost::mpl::integral_c<long,2584>,boost::mpl::integral_c<long,4181>,FizzBuzz,boost::mpl::integral_c<long,10946>,boost::mpl::integral_c<long,17711>,boost::mpl::integral_c<long,28657>,Fizz,Buzz,boost::mpl::integral_c<long,121393>,boost::mpl::integral_c<long,196418>,Fizz,boost::mpl::integral_c<long,514229>,Buzz,boost::mpl::integral_c<long,1346269>,Fizz,boost::mpl::integral_c<long,3524578>,boost::mpl::integral_c<long,5702887>,Buzz,Fizz,boost::mpl::integral_c<long,24157817>,boost::mpl::integral_c<long,39088169>,boost::mpl::integral_c<long,63245986>,FizzBuzz>
||         ]

mpl::print を使用しているので、コンパイル時に結果も出力します。
msvc が多分一番見やすいと思う。


あと正しくメモ化されるために fibonacci には type を渡しています。

fibonacci<typename mpl::minus<N, mpl::long_<1> >::type>

mpl::minus > をそのまま渡すと正しくメモ化されないで、メモリが死にそうになりました。