mpl::switch_ で、FizzBuzz

やりました。
久々にメタメタして楽しかったです。

#include <boost/mpl/switch.hpp>
#include <boost/mpl/print.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/string.hpp>
#include <boost/mpl/always.hpp>
#include <boost/mpl/modulus.hpp>

namespace mpl = boost::mpl;
using mpl::_1;

typedef  mpl::string<'fizz'>          fizz;
typedef  mpl::string<'buzz'>          buzz;
typedef  mpl::string<'fizz', 'buzz'>  fizz_buzz;

typedef
    mpl::equal_to<mpl::modulus<_1, mpl::int_<3> >, mpl::int_<0> >
is_fizz;

typedef
    mpl::equal_to<mpl::modulus<_1, mpl::int_<5> >, mpl::int_<0> >
is_buzz;

typedef mpl::vector<
    mpl::pair<
        mpl::and_<is_fizz, is_buzz>,
        mpl::always<mpl::c_str<fizz_buzz> >
    >,
    mpl::pair<
        is_fizz,
        mpl::always<mpl::c_str<fizz> >
    >,
    mpl::pair<
        is_buzz,
        mpl::always<mpl::c_str<buzz> >
    >,
    mpl::pair<mpl::always<mpl::true_>, _1>
> case_fizz_buzz;


#include <iostream>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/range_c.hpp>

struct print{
    template<typename T>
    void operator()(T){
        typedef typename mpl::switch_<case_fizz_buzz, T>::type result;
        std::cout << result::value << ",";
    }
};

int
main(){
    mpl::for_each< mpl::range_c<int, 1, 20> >( print() );
    return 0;
}

[出力]

1,2,fizz,4,buzz,fizz,7,8,fizz,buzz,11,fizz,13,14,fizz_buzz,16,17,fizz,19,


mpl::switch_ は、アンドキュメントなので、使用する際は頑張ってください。
mpl::print とともにドキュメントが欲しいですねぇー。


[boost]
ver 1.46.1