Boost.勉強会.Aftercare
「質問タイムで回答しか聞こえねー」というご意見をいくつかいただいたので、思いだしながら補足したいと思います。hirataraさんもまとめてくださっていますので、そちらもご覧ください。
あと私のプリプロセッサ関連のエントリーまとめも置いときますね。
質疑応答で私が答えた内容については、 ustream の私の発表から確認してみてください。自分の発表を見るとか怖いので、まだ見てません。
※この先は「Boost.」を省略しています。using namespaceします。
なんでそんなクレイジーなことしているのですか?(どうしてプリプロセッサでプログラミングをしようと思ったのですか?)
クレイジーだからです。というか私がクレイジーかどうかはさて置いて、このライブラリは当然Boostを実装するということが主目的で作られているので、本当に手段を問わないライブラリだと思います。ただ、手段を問わないといっても、C++の範囲内でやってる、という点ですごいです。
C++0xになると、右辺値参照とか可変長テンプレート引数とか入るけど、それでどれぐらいプリプロセッサは削減できるの?
プリプロセッサの仕分けですね分かります。まぁむしろ仕分けできないほうが不健全ではあるので、仕分けしてください。
template<typename T1> void f(T1 t1) { return g(t1); } template<typename T1, typename T2> void f(T1 t1, T2 t2) { return g(t1, t2); } template<typename T1, typename T2, typename T3> void f(T1 t1, T2 t2, T3 t3) { return g(t1, t2, t3); }
というような、引数の数だけが違うテンプレート関数を作ることが多く、そのたびに上のように並べていられないので、C++03では発表であったようにプリプロセッサでn引数版の関数を大量に作っていました。
が、C++0xでは、テンプレート引数(typename TNの部分)を可変長にすることができるようになるのと、const/非const についてもforward関数テンプレート(詳細は割愛)を利用すれば一括して記述できるので、
template<typename ...T> void f(T && ...t) { return g(std::forward<T>(t)...); }
と書くだけで、n引数版オーバーロードや、更にその引数ごとのconst/非constの組み合わせ別の大量生産は不要になります。で、
shared_ptr の make_shared, Tuple, Fusion, Function, Bind あたりにそういう関数、関数テンプレート、型テンプレートがあるので、まずはこれらから消えます。特にMPLはvectorがすさまじいことになっているので、誰かとめるべきです。逆に ScopeExit, Parametersのような、擬似的に新しい構文を作る系で繰り返している箇所はそのまま残るかと思います。構文を変えればもしかすればVariadic Templateに持ち込めるかもしれないですが。それと、C++0xではVariadic Parameterが入るっぽいので、Boost.PPもダイエットできます。具体的には、プリプロセス時のタプルにn引数版が必要なくなります。
#define BOOST_PP_TUPLE_REM(...) __VA_ARGS__ #define BOOST_PP_TUPLE_ELEM(n, tup) BOOST_PP_TUPLE_ELEM_I(n, tup) #define BOOST_PP_TUPLE_ELEM_I(n, tup) BOOST_PP_TUPLE_ELEM_ ## n(tup) #define BOOST_PP_TUPLE_ELEM_0(a, ...) a #define BOOST_PP_TUPLE_ELEM_1(a, b, ...) b #define BOOST_PP_TUPLE_ELEM_2(a, b, c, ...) c #define BOOST_PP_TUPLE_ELEM_3(a, b, c, d, ...) d #define BOOST_PP_TUPLE_ELEM_4(a, b, c, d, e, ...) e #define BOOST_PP_TUPLE_ELEM_5(a, b, c, d, e, f, ...) f
で、任意の要素数のタプルに対応できるようになります。が、あのライブラリが更新されるかどうかは知りません。あと、可変長引数マクロの効果は他にもあって、タプルをconsのように扱える、つまりSequenceやListと同じように扱うことができるようになります。なので、現在ScopeExitでキャプチャ変数の指定は(x)(y)(z)と書きますが、これを(x, y, z)と、C++的に自然な書き方に改めることもできるようになります。まぁ、ラムダ式が使えれば全く問題はなかったりしますが、それでも構文糖としての価値はまだ残って…いると…信じたい…。
コンパイル時やプリプロセス時にも副作用が起こせるべきですよねそう思いませんか?
そんな規模のコードをコンパイル時やプリプロセス時に走らせるのは止めるべきです死にますコンパイラが。codepadもタイムアウトします。まぁでもC++使う人とか副作用なんて全然分からないですし、型レベルならHaskell的な頑張りでやればいいんじゃないですかね?悪い子です。あとプリプロセス時なら、式っぽさにこだわらなければ、
incr.hpp #define BOOST_PP_VALUE BOOST_PP_SLOT(1) + 1 #include BOOST_PP_ASSIGN_SLOT(1)
#define BOOST_PP_VALUE 0 #include BOOST_PP_ASSIGN_SLOT(1) BOOST_PP_SLOT(1) // 0 #include "incr.hpp" BOOST_PP_SLOT(1) // 1 #include "incr.hpp" BOOST_PP_SLOT(1) // 2 #include "incr.hpp" BOOST_PP_SLOT(1) // 3 #include "incr.hpp"
とかできて楽しいです。あと#include にコンソール入力とか指定できれば対話環境とか、そういうってどうなんですかね?
デバッグとかどうするのですか?
実行すれば分かるのでデバッグとかいらないですし、テンプレートと同じで人間のほうがプリプロセス展開後の意図しない展開の原因が分かるように歩み寄っていきますので、いらないです。あとデバッグが必要なほどの巨大なメタプログラムの塊を放り込むのは止めてくださいプリプロセッサまたはコンパイラに対してサディスティックすぎます。
ステップ実行したいのですが?
最近はVCとgccについては脳内ステップ実行できるようになったので、みなさんも頭にインストールすればいいです。