いま流行のFizzBuzzを純粋関数型言語C++で書いてみた
73行。boost/mplやboost/lambda駆使すれば20行くらいになるかな?
なんかあんまり純粋関数な感じしないんだよね微妙。
template<bool cond,typename th,typename el> struct if_; template<typename th,typename el> struct if_<true,th,el> { typedef th result; }; template<typename th,typename el> struct if_<false,th,el> { typedef el result; }; template<int n> struct int_{}; struct fizz {static const char* str;}; struct buzz {static const char* str;}; struct fizzbuzz {static const char* str;}; const char* fizz::str="Fizz"; const char* buzz::str="Buzz"; const char* fizzbuzz::str="FizzBuzz"; struct filter { template<int n> struct exec { typedef typename if_<n%15==0, fizzbuzz, typename if_<n%3==0,fizz, typename if_<n%5==0,buzz, int_<n> >::result >::result >::result result; //cooool!! }; }; template<typename t> struct to_value { static inline const char* get() { return t::str; } }; template<int n> struct to_value<int_<n> > { static inline int get() { return n; }; }; #include <iostream> using std::cout; using std::endl; template<int start,int end> struct int_sequence { static const int value=start; typedef int_sequence<start+1,end> next; template<typename body> inline static void print_each() { //このbody::template execって記法がわかんなかったんだよ。今回唯一の収穫 cout << to_value<typename body::template exec<value>::result>::get() << " "; next::template print_each<body>(); } }; template<int start_end> struct int_sequence<start_end,start_end> { static const int value=start_end; typedef void next; template<typename body> inline static void print_each() { cout << to_value<typename body::template exec<value>::result>::get(); } }; int main() { int_sequence<1,100>::print_each<filter>(); cout << endl; }
このコードをコンパイルすると、なんと!
int main() { cout << 1 << " "; cout << 2 << " "; cout << "Fizz" << " "; //(snip) cout << 98 << " "; cout << "Fizz" << " "; cout << "Buzz"; cout << endl; }
と等価なコードが出力されます。
何が嬉しいんだ。
剰余を使わないバージョンもかいてみた(inspired by http://d.hatena.ne.jp/cxx/20070517/1179341986 )
template<typename car,typename cdr> struct cons{ typedef car car; //あ、通るんだこれ typedef cdr cdr; }; struct num {static int get(int n){return n;}}; struct fizz {static const char* get(int){return "Fizz";}}; struct buzz {static const char* get(int){return "Buzz";}}; struct fizzbuzz{static const char* get(int){return "FizzBuzz";}}; typedef cons<num,cons<num,cons<fizz, cons<num,cons<buzz,cons<fizz, cons<num,cons<num,cons<fizz, cons<buzz,cons<num,cons<fizz, cons<num,cons<num,cons<fizzbuzz,void>>> >>> >>> >>> >>> fb; //これはひどい #include <iostream> using std::cout; using std::endl; template<int c,typename j> struct FizzBuzz { template<typename list> struct next {typedef typename list::cdr result;}; template<typename car> struct next<cons<car,void>> {typedef fb result;}; static void exec() { cout << j::car::get(c); FizzBuzz<c+1,next<j>::result>::exec(); } }; template<typename j> struct FizzBuzz<101,j> { static void exec() {} }; int main() { FizzBuzz<1,fb>::exec(); cout << endl; }
なんか凄く短くなった><