任意の expression に透過的に hook を仕掛けるようなマクロが書けるのではありませぬか?

以下のコードでやっていることの説明.

EXCEPTION_HOOK((expr))

と書いておけば, (expr) という C++ の式を実行したら急に例外が来たので……というときに, call stack のようなもので殴られた跡 (この hook が仕掛けられている場所に関する情報) を boost::exception に乗せていきます. call stack の生成ぐらい言語でサポートして欲しいよね,うんうん.終わり. Microsoft Visual C++ 2010 と GCC 4.5.0 で動作を確認済みです.

工夫として,

EXCEPTION_HOOK((expr))

という文字列が式 expr と同等な C++expression として透過的に機能するように見せかけてあります.つまり,たとえば

std::string s("42");
int i = EXCEPTION_HOOK((boost:lexical_cast<int>(s)));

などと書けるようにしてあり,もちろん例外が通知されなければこのコードは

std::string s("42");
int i = boost::lexical_cast<int>(s);

と同じ挙動を示します.終わり.

透過性という点で重要な別の特徴として, preprocessing-time でこの hook を完全に無効化できます.無効化して,字句レベルで (expr) という構文として振舞わせるのは赤子の手をひねる (それをするなんてとんでもない!) よりも造作のないことよ,クックック…….

以下のコードの要点 ([&]lambda-introducer を伴う lambda-expression を用いて, hook を仕掛けた場所のスコープの文脈を持ち込みつつコールバック化する点) さえ抑えておけば,任意の expression に対して,透過的に preprocessing-time, compile-time, runtime レベルの pre-hook, post-hook および例外送出時 hook を仕掛けるようなマクロ (「えーマジマクロ?」「マクロが許されるのは……」) を構築できるんじゃないんでしょうか,知らんけど?

細かいこと言うと hook を仕掛ける対象となる式の型が void でない場合は MoveConstructible でないといけないという制約がががが.ただし,過去,似たようなものはいくつか提示されていますが (Bjarne が昔書いていた operator-> で hook を書く記事どこいったっぽ? *1 ) ,「hook を仕掛ける構文がそのまま expression として透過的に扱える」かつ「例外送出イベントにも hook を仕掛けられる」というのを C++ で達成したものはなかったはずなのでにょほほほほ.

以下,とても長〜いコードと出力例.

*1:追記:あった. リンク先 PDF 注意 http://www2.research.att.com/~bs/wrapper.pdf

続きを読む