パスワードを忘れた? アカウント作成
191184 journal

Yak!の日記: C/C++ で Quantum::Superpositions リベンジ

日記 by Yak!

ふと思い立って本名ローマ字で検索してみたら FreeBSD Foundation の donor に名前が載っていたり(名前が載るのは知らなかった)、"baldr sky 小説"でこの日記のエントリが検索トップになったり。ちなみに BALDR SKY の小説自体はなごみ文庫公式の発売予定からも消えてしまっている。特典でも真ルートは煮詰まっていたとの言があったので、恐らく卑影先生が順当に煮詰まっているものと思われる。出てほしいんだけどなぁ……。

閑話休題。

てっきり日記のエントリにしていたと思ったら実はしていなかったのだが、その昔、C++ 版 Quantum::Superpositions なるものを作成した事がある。その時、某所では「ショートサーキット評価できないだろうが、ボケが!」との暖かい罵声を頂いた(注:ショートサーキット評価に関してアホなレスを返した為なので。念のため)。とはいえ、現行 C/C++ の範囲内では、引数の遅延評価を実現するのは難しい(全て template で書くとか、C++0x なら lambda に押し込めればありかも)。しかし、C/C++ 規格内にありながら、C/C++ の構文、意味論の埒外にいるものが存在するのである。そう、preprocessor である。

ということで、2年と半年くらいの時を超えて Boost PreProcessor を使って、Quantum::Superpositions を再実装してみた。他にやることあるだろうという気がするがそこはそれ。使用例はこんな感じである。

if(QSP(QSP_ANY(1)(2), ==, QSP_ARG(1)))
{ /* ((1==1)||(2==1)) に展開 */ }
if(QSP(QSP_ANY(1)(2), ==, (1)))
{ /* QSP_ARG は省略可能(括弧は必要) */ }
if(QSP((1), ==, QSP_ALL(1)(2)))
{ /* ((1==1)&&(1==2)) に展開 */ }
if(QSP(QSP_ANY(1)(2), ==, QSP_ALL(1)(2)))
{ /* (((1==1)&&(1==2)) || ((2==1)&&(2==2))) に展開。右辺が先に変化 */ }

C++ 版とは違って多段はできない。本当にその場に式を展開しているので挙動については推して知るべしである。例えば引数に関数呼び出しがあったりすると毎回呼びだされる。ただし、ショートサーキット評価の形で。

書いてる中で気付いた Boost PreProcessor の落とし穴について一応メモしておく。

  • 当たり前と言えば当たり前なのだが、BOOST_PP_IIF とかでは真偽両方が展開される。

    BOOST_PP_IFF(BOOST_PP_GREATER(BOOST_PP_SEQ_SIZE(seq), 3), BOOST_PP_SEQ_FIRST_N(3, seq), seq)
    //気分的には if(seq.size() > 3) { return seq.first(3); } else { return seq; }

    と書いた場合、BOOST_PP_GREATER(BOOST_PP_SEQ_SIZE(seq), 3) が偽の場合でも、BOOST_PP_SEQ_FIRST_N(3, seq) の展開自体はされるため(seq のサイズが足りなくて)エラーが発生する。

    BOOST_PP_IFF(BOOST_PP_GREATER(BOOST_PP_SEQ_SIZE(seq), 3), BOOST_PP_SEQ_FIRST_N(BOOST_PP_MIN(3, BOOST_PP_SEQ_SIZE(seq)), seq), seq)

    のような感じにしておけば良い。

  • BOOST_PP_SEQ_FOR_EACH_I は reentrant ではない。
    おそらく _D, _Z, _R が大文字になってるシリーズも reentrant じゃなさそう。reentrant な BOOST_PP_REPEAT 等を使うか、この辺のスレッドを参照して、BOOST_PP_SEQ_FOR_EACH と BOOST_PP_SEQ_FOR_EACH_I の複合技を使うとか。

実装はここから。

この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
typodupeerror

アレゲは一日にしてならず -- アレゲ見習い

読み込み中...