深すぎちゃった

再帰が深すぎてstack overflowしちゃった.テヘ☆
つーか俺使い方間違ってないよな〜?(使っているライブラリの中でstack overflowする)ま〜,内部実装如何ではstack overflowも起きかねないことやらせてるんだけれど,一方でこれぐらいでstack overflowされるのはちと困るという気も・・・.ソース解析すれば良いのだけれど,そんなことするぐらいなら自分で最初から組みたいしな〜.(インターフェースがちとレガシーで,効率落とさずにインターフェースアダプタかますのが無理)
組みなおしたいもう一つの理由がライセンスで,LGPLなテンプレートライブラリなんだけど,実際LGPLでテンプレートライブラリってどうなんだろ?個人的に非常に気持ち悪いんだけれどにゃ〜.ま〜個人的にはGPL好きじゃないというのがあるんだけれど,それは個人の嗜好だからどーでも良い.
#っていうか要するにどっちに転んでもおかしくない(成果物(obj)をGPL相当で扱わないといけない可能性を排除できない)つーことジャン.う〜.
全然関係ないけれど,末尾再帰だけとかケチ臭いこといわずに一般の再帰をフリーストア上のスタックによる実装にぺぺぺ〜と書き換えてくれるよ〜なヤツにゃいかにゃ〜.にゃいだろうにゃ〜.

for each

あ〜もうくそぅ!!俺は↓がやりたいねん!!

std::vector<int> v;
v.push_back(0);
v.push_back(1);
v.push_back(2);
FOREACH(it, v){ // ←これがやりたい.これがっ!!
  std::cout << *it << std::endl;
}

あーーー!!あーーー!!あーーーーー!!!!!11
何でできないかな,くそぉ・・・・.あーーーーーーーっ!!!イライラするーーーーーーーぅ!!!

なんでイライラするか

そもそもfor文でコンテナ回すと面倒くさくて仕方ないでしょ?

for(vector<int>::const_iterator it(v.begin()); it != v.end(); ++it){
  std::cout << *it << std::endl;
}

で,BOOST_FOREACH(ここのforeach.zip展開してboostのフォルダにforeach.hpp突っ込めばとりあえず使えます.詳細はドキュメント参照)はそれをだいぶ解消してくれてC++に無名関数がないという不満もだいぶ少なくなる(消滅はしない)けれど,まだ個人的に不満があって何がダメなのかというと

  • BOOST_FOREACHはvalue_typeに言及しないといけないので面倒
  • BOOST_FOREACHは値のコピーを取らないといけないので効率が気になる.(実際には参照を宣言して回避できるもののそれがまたイヤンな感じ)

前者はvalue_typeが比較的複雑なときに面倒.

std::vector<std::pair<int, int> > pair_vec;
BOOST_FOREACH(std::pair<int, int> p, pair_vec){

じゃあ,value_typeをtypedefすればよいじゃないかという話はあるけれどそうすると今度はそのtypedefが面倒.
要するにvalue_typeもしくはiteratorに「全く言及せずに」「それでいて型安全に」iterationをまわしたい.
で,これだと要するにtypeofを要求することになるので「それ無理ですから」といわれればそれで諦めが付くんだけれど,実際自分が欲しているようなFOREACHのエミュレーション手法を思いついたのが運の尽き.で,実際やってみたら一見全然関係ないこの仕様がとことん邪魔をしてVC7.1で実装できない(GCCだとできる)という超ムキー!!な状態が発生してここまでイライラするという・・・.いやまぁ,このVC7.1の仕様は言語規格的には正しいっぽいんですけどね・・・.

BOOST_FOREACHの実装技法

あ,全然関係ないですけれどBOOST_FOREACHの実装技法はかなり難解な部類なものの,分かるとかなり楽しいです.scope guardに見られるような,派生クラスをオブジェクトジェネレータで生成して,生成された一時オブジェクトの寿命を基底クラスのconst参照で延命するという技法が使われています.scope guardの場合,stack unwinding(例外が飛んでスコープを抜ける場合に,スコープを外れたオブジェクトのデストラクタが自動的に呼ばれる動作のこと)でデストラクタが発動されるまで,要するにスコープの終端までその一時オブジェクトを延命すればよいだけですが,FOREACHの場合基底クラスのconst参照で延命しつつ生成した一時オブジェクトの実際の型を関数テンプレートの型推論能力を用いて復元しているように見せかけています.さらにこれを自然な単一のfor文に見せるために,if文の条件文中でboolに変換可能な型が宣言できることを利用してcascadeしまくったif文を用いるという,っていうか説明読むより実装読んだ方が早いです.あと,foreachのzipになぜかこの実装技法を説明したpptファイルが付いてます(笑)のでそれが非常に参考になります.