mplとlambdaで遊んだFizzBuzz問題
#include <iostream>
#include <boost/mpl/if.hpp>
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/lambda/lambda.hpp>
namespace mpl = boost::mpl;
namespace lambda = boost::lambda;
struct Fizz {operator const char*() {return "Fizz";}};
struct Buzz {operator const char*() {return "Buzz";}};
struct FizzBuzz {operator const char*() {return "FizzBuzz";}};
template <typename T> struct Integer
{operator typename T::value_type() {return T::value;}};
template <typename T>
struct fizzbuzz_translator
{
typedef
typename mpl::if_c<!(T::value%15), FizzBuzz,
typename mpl::if_c<!(T::value%3), Fizz,
typename mpl::if_c<!(T::value%5), Buzz,
Integer<T>
>::type >::type >::type type;
};
int main()
{
mpl::for_each<
mpl::range_c<int,1,101>,
fizzbuzz_translator<mpl::_1> >
(std::cout << lambda::_1 << '\n');
return 0;
}
見苦しい言い訳をさせてくれ
こんなコードになる予定じゃなかったんだ
最初はboost::lambda::ifとかで遊んでみようかと思ってたのに
boost::lambda自体を使ったことなかったこともあって
エラー潰している内にこんなコードに...○| ̄|_
書いてみようかと思ったきっかけはこのページのコード
このコードが既にC++にすら見えないと思ったのと
「lambdaだけでも十分に従来のC++から外れないか?」と思い
帰宅してちゃかちゃかと組んでみたんだけど随分と太ったコードがが
どうせなら、全部マクロとかで作るとかのほうが面白かったかと後悔中
# つってもboost::preprocessorでのたうち回っている最中だから
# どの道、今の状態じゃマクロだけで組むとか無理('A`)
遊びで組んだコードで凹むとか、か弱すぎるぞ、おいら...○| ̄|_
フィードバック
# re: 【C++】FizzBuzz問題でお勉強
2007/11/08 10:59 by
Integral Constantはvalue_typeに変換できるのでIntegerは不要です.
もっとMPL使ってこんな感じに 笑
template <class T>
struct fizzbuzz_translator :
mpl::eval_if<mpl::not_<mpl::modulus<T, mpl::int_<15> > >,
mpl::identity<FizzBuzz>,
mpl::eval_if<mpl::not_<mpl::modulus<T, mpl::int_<3> > >,
mpl::identity<Fizz>,
mpl::if_<mpl::not_<mpl::modulus<T, mpl::int_<5> > >,
Buzz,
T
>
>
>
{ };
mpl::quote1<fizzbuzz_translator>
# re: 【C++】FizzBuzz問題でお勉強
2007/11/08 11:34 by
うーん・・・
#include <iostream>
#include <boost/preprocessor/control/if.hpp>
#include <boost/preprocessor/comparison/equal.hpp>
#include <boost/preprocessor/arithmetic/mod.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#define fizzbuzz(z, x, _) \
BOOST_PP_IF(BOOST_PP_EQUAL(BOOST_PP_MOD(x, 15), 0), \
std::cout << "FizzBuzz" << std::endl;, \
BOOST_PP_IF(BOOST_PP_EQUAL(BOOST_PP_MOD(x, 3), 0), \
std::cout << "Fizz" << std::endl;, \
BOOST_PP_IF(BOOST_PP_EQUAL(BOOST_PP_MOD(x, 5), 0), \
std::cout << "Buzz" << std::endl;, \
std::cout << x << std::endl; \
) \
) \
) \
/**/
int main()
{
BOOST_PP_REPEAT_FROM_TO(1, 51, fizzbuzz, ~)
}
# re: 【C++】FizzBuzz問題でお勉強
2007/11/08 13:27 by
>Integral Constantはvalue_typeに変換できるのでIntegerは不要
そいやそうだった
最初、mpl::for_eachの()の中でlambda::ifを使おうとして
integral_cに%のoperatorがなくて無理にwrapし
そしてそれがそのまま残ってたーよ
>もっとMPL使ってこんな感じに 笑
ありがとうございます(色々と目からポロポロと...
eval_ifの存在をすっかり忘れていたのと
別にわざわざtypedefしなくても継承しときゃ良いんだよなーと
# んで、eval_if使えば自然と直接数値計算しないので
# 自動的に全部mplでまかなうようになり
# typename指定もいらなくなると...
>mpl::quote1<fizzbuzz_translator>
実はこのコードで一番頭抱えてたのがこの部分
for_eachの第二引数をどう指定すればよいのかわからなくて
サンプルを見よう見まねでmpl::_1渡していたんです
# そうだよね、for_each_impl見たら
# こいつはapplyに渡されるんだからquoteで良いんだよね
うん、やっぱり100読むよりも1書いたほうが
あきらかに勉強効率としは良いようだね
ホント、使ってみないと憶えられないわw
# re: 【C++】FizzBuzz問題でお勉強
2007/11/08 13:35 by
って、ちょwwww
開きっぱなしで放置してコメントしたらpreprocessor版がw
# これから見ます
# re: 【C++】FizzBuzz問題でお勉強
2007/11/08 13:43 by
>別にわざわざtypedefしなくても継承しときゃ良いんだよなーと
継承して新しいメタ関数を作るテクニックはmetafunction forwardingと呼ばれてます.
lambda::ifでならこんな感じですかね.
#include <iostream>
#include <algorithm>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/if.hpp>
#include <boost/iterator/counting_iterator.hpp>
int main()
{
namespace bll = boost::lambda;
using bll::_1;
std::for_each(
boost::make_counting_iterator(1),
boost::make_counting_iterator(101),
bll::if_(!(_1 % 15))
[
std::cout << bll::constant("FizzBuzz") << '\n'
]
.else_
[
bll::if_(!(_1 % 3))
[
std::cout << bll::constant("Fizz") << '\n'
]
.else_
[
bll::if_(!(_1 % 5))
[
std::cout << bll::constant("Buzz") << '\n'
]
.else_
[
std::cout << _1 << '\n'
]
]
]
);
}
# re: 【C++】FizzBuzz問題でお勉強
2007/11/08 14:25 by
preprocessor版の動作確認して
第一印象:うわ、ホントにできたよ
第二印象:そうか、回数増やすとそりゃコンパイルが...
第三印象:本当にネタ以外の何者でもないなw
という感想
おいらの頭じゃ、寝た以外で数値処理するメリットなさそうね
やっぱり、preprocessorはclassやfunctionの量産用か...
# つーか、本当にpreprocessor絡みは見るの辛い...○| ̄|_
# 書いてみてデバッグ実行でコード追えないのってこんなに辛いのか
>別にわざわざtypedefしなくても継承しときゃ良いんだよなーと
>継承して新しいメタ関数を作るテクニックはmetafunction forwarding
名前まであるのか!?(゚Д゚)
>lambda::ifでならこんな感じですかね.
何から何までありがとうございます
lambda::constantで死んでいた謎が氷解しました
つーか、自分でコード書いていて思ったけど
やっぱりこうして見るとelse_if記述がないのは面倒だなぁ
# re: 【C++】FizzBuzz問題でお勉強
2007/11/08 21:12 by
>mpl::quote1<fizzbuzz_translator>
for_eachはLambda Expressionを要求していたので,fizzbuzz_translator<mpl::_1>(またはfizzbuzz_translator<mpl::_>)でも大丈夫だと思ったのですが,コンパイルエラーになってしまったのでquote1でmetafaunction classにしてやりました.mpl::lambdaでmetafaunction classにしてもいけます.
ただ,今のところなぜエラーになるのかよくわかってないので,ちょっと調べてみます(for_each_implの中のapply1はPlaceholder Expressionを受け付けるはず).多分ぼくがテンプレートのインスタンス化のタイミングを完全に把握して無いのが原因だと思いますが.
# re: 【C++】FizzBuzz問題でお勉強
2007/11/09 11:29 by
>fizzbuzz_translator<mpl::_1>
ふむ、もうほとんど話しについていけなくなってるのだが
元々おいらのfizzbuzz_translatorはこっちでもいけていたので
こいつを元に(動けば良いってもんじゃないが)パズルをしてみる
template <typename T>
struct fizzbuzz_translator :
mpl::identity<
mpl::eval_if<
mpl::not_< mpl::modulus<T, mpl::int_<15> > >,
FizzBuzz,
mpl::eval_if<
mpl::not_< mpl::modulus<T, mpl::int_<3> > >,
Fizz,
mpl::eval_if<
mpl::not_< mpl::modulus<T, mpl::int_<5> > >,
Buzz,
T
>
>
>
>
{};
とりあえず、これでOK(VC++2005EE)なんだが
何でこれがOKで前回のが駄目なにかサッパリだーね
うー、精進足らんのは当然なんだが、
やっぱり根本的にtemplateはエラーが読みにくいなぁ...
# type_traitsの小洒落た使い道って何だろう?
2008/01/13 3:06 by
type_traitsの小洒落た使い道って何だろう?
# pEyfCUENaqwO
2014/08/07 2:17 by
iBoLzF Very informative blog post. Really Great.
# hCTyuQGlLSbwhxjD
2014/09/03 12:14 by
I'd must check with you here. Which is not one thing I usually do! I take pleasure in studying a submit that may make individuals think. Also, thanks for allowing me to comment!
# GyDcQTqGIoeA
2014/09/11 21:14 by
whoah this blog is fantastic i like studying your articles. Stay up the great paintings! You realize, many persons are looking round for this info, you can help them greatly.
# NYuuMmibGVIBg
2014/09/15 8:24 by
Hi there, I found your website via Google at the same time as looking for a related matter, your website got here up, it looks good. I have bookmarked it in my google bookmarks.
# EQwfsXIYKwdZrXc
2014/09/18 17:24 by
SHhJdk I appreciate you sharing this post.Thanks Again. Awesome.