テンプレートメタプログラミング
      as 式
北海道のみなさま、こんにちは
●   なぜ知ってる人が多いのですか?
自己紹介
●   きりんさんが好きです。でもC++さんのほうがもーっと
    好きです。
●   twitter: @decimalbloat
●   hatena: id:DigitalGhost
●   過去の発表:
    ●   プリプロセス時プログラミングの話 (Boost.勉強会 #1)
        http://sites.google.com/site/boostjp/study_meeting/study1
    ●   プリプロセス時ラムダ式 (Boost.勉強会 #2)
        http://sites.google.com/site/boostjp/study_meeting/study3
プリプロセッサの話だと思った?
●   残念、templateちゃんでした!
●   当初は「パターンマッチ on C++」と題して、
    関数型言語ではおなじみのパターンマッチを、
    コンパイラとプリプロセッサの虐待の末 C++
    上で作ったという話をする予定でしたが、遅々
    として進まなかったので急遽変更しました。
TMPとは
●   クラステンプレートを、型(やコンパイル時に
    扱える値)を受け取ってnested-typedefの
    typeという名前を戻り値とする関数とみなし
    て行うプログラミング
●   これを使ってコンパイル時にパラメータから型
    を自動生成したり、関数(普通の)の引数の型か
    ら戻り値の型を求めたりする
もっとかっこよくTMPしたい
●   どうせならremove_reference(T) x;とか
    できたらカッコいいじゃないですか
●   そんなわけで作ってみました
式でメタプログラミングできないか
●   型から対応する値を作り出し、その値を操作す
    ることでメタプログラミングする。
metaexpr
●   https://github.com/dechimal/metaexp
    r.git
remove_reference
    using namespace metaexpr; // 例なので…

    auto remove_reference =
      METAEXPR_FUN((p0 x) -> decltype(
        match(x)
            | when<type_t<p1 &> >(METAEXPR_VALUEOF(p1))
            | when<type_t<_> >(x)));

●   カッコいい(当人比)
使う側
    METAEXPR_RUN(
        remove_reference(
            METAEXPR_VALUEOF(int &))) x;
●   カッコい…うーん(当人比)
型と値
●   型から式を得る
    ●   METAEXPR_VALUEOF(type)
        もしくは
    ●   val<type_t<type> >()
●   式から型を得る
    ●   METAEXPR_RUN(expr)
        もしくは
    ●   decltype(run(expr))
関数
●   METAEXPR_FUN(
        (holder1 name1, holder2 name2, …) ->
            decltype(expr))
●   fun_t<
        auto (holder1 name1, holder2 name2, …) ->
            decltype(expr)>()
●   C++11の新機能、後置した関数の戻り値型を利用して、
     auto fun(p0 x, p1 y)->decltype(f(x, g(y)))
    とか書けば、なんとなくxとyを引数にとってf(x, g(y))を返す関数そ
    のものを定義している気になれるので、metaexpr上の関数においては、
    本当にそれを関数とみなすことにした。
     (p0とかp1は関数の引数であることを表わす型、fやgはmetaexpr上の関数)
例
●   auto f =
        METAEXPR_FUN((p0 x, p1 y)->decltype(
             f(x, g(y))
        ));
●   auto f =
        fun_t<auto (p0 x, p1 y)->decltype(
             f(x, g(y))
        )>();
パターンマッチ
●   match(value) | when<pattern>(expr)
                 | …
●   valueがpatternと同じ構造であれば、
    (pattern内で/その外側で)束縛された変数で
    exprを評価する。そうでなければ次のwhen節
    を試す
●   最後のwhen節でマッチできなければエラー
例
●   auto f = METAEXPR_FUN((p0 x) -> decltype(
        match(x)
            | when<type_t<p0 &> > (METAEXPR_VALUEOF(p0 const &))
                // a) xがT const &だったらT
            | when<f<p0, p1> >(METAEXPR_VALUEOF(f<p1, p0>))
                // xがf<T, U>だったらf<U, T>
            | when<_>(METAEXPR_VALUEOF(int)));
                // xによらずint

●   p0とかp1は、その位置に対応する型に束縛される。例え
    ばxがみたいな型だった場合、(a)のexpr内のp0はintに
    置き換えられる
●   _は何にでもマッチする
今後の課題
●   実装のほうは思いつきで作り始めたままなので
    色々おかしい、というかまだ実装途中
     (remove_const作っても動かないし高階関数は使
     えない、再帰関数を定義できない、など)
●   クラステンプレートによるメタ関数みたいに特
    殊化でAd-hocに挙動変更とかはできないのを
    なんとかする
参考
●   http://svn.boost.org/svn/boost/
    sandbox/ftmpl/

テンプレートメタプログラミング as 式

  • 1.
  • 2.
    北海道のみなさま、こんにちは ● なぜ知ってる人が多いのですか?
  • 3.
    自己紹介 ● きりんさんが好きです。でもC++さんのほうがもーっと 好きです。 ● twitter: @decimalbloat ● hatena: id:DigitalGhost ● 過去の発表: ● プリプロセス時プログラミングの話 (Boost.勉強会 #1) http://sites.google.com/site/boostjp/study_meeting/study1 ● プリプロセス時ラムダ式 (Boost.勉強会 #2) http://sites.google.com/site/boostjp/study_meeting/study3
  • 4.
    プリプロセッサの話だと思った? ● 残念、templateちゃんでした! ● 当初は「パターンマッチ on C++」と題して、 関数型言語ではおなじみのパターンマッチを、 コンパイラとプリプロセッサの虐待の末 C++ 上で作ったという話をする予定でしたが、遅々 として進まなかったので急遽変更しました。
  • 5.
    TMPとは ● クラステンプレートを、型(やコンパイル時に 扱える値)を受け取ってnested-typedefの typeという名前を戻り値とする関数とみなし て行うプログラミング ● これを使ってコンパイル時にパラメータから型 を自動生成したり、関数(普通の)の引数の型か ら戻り値の型を求めたりする
  • 6.
    もっとかっこよくTMPしたい ● どうせならremove_reference(T) x;とか できたらカッコいいじゃないですか ● そんなわけで作ってみました
  • 7.
    式でメタプログラミングできないか ● 型から対応する値を作り出し、その値を操作す ることでメタプログラミングする。
  • 8.
    metaexpr ● https://github.com/dechimal/metaexp r.git
  • 9.
    remove_reference using namespace metaexpr; // 例なので… auto remove_reference = METAEXPR_FUN((p0 x) -> decltype( match(x) | when<type_t<p1 &> >(METAEXPR_VALUEOF(p1)) | when<type_t<_> >(x))); ● カッコいい(当人比)
  • 10.
    使う側 METAEXPR_RUN( remove_reference( METAEXPR_VALUEOF(int &))) x; ● カッコい…うーん(当人比)
  • 11.
    型と値 ● 型から式を得る ● METAEXPR_VALUEOF(type) もしくは ● val<type_t<type> >() ● 式から型を得る ● METAEXPR_RUN(expr) もしくは ● decltype(run(expr))
  • 12.
    関数 ● METAEXPR_FUN( (holder1 name1, holder2 name2, …) -> decltype(expr)) ● fun_t< auto (holder1 name1, holder2 name2, …) -> decltype(expr)>() ● C++11の新機能、後置した関数の戻り値型を利用して、 auto fun(p0 x, p1 y)->decltype(f(x, g(y))) とか書けば、なんとなくxとyを引数にとってf(x, g(y))を返す関数そ のものを定義している気になれるので、metaexpr上の関数においては、 本当にそれを関数とみなすことにした。 (p0とかp1は関数の引数であることを表わす型、fやgはmetaexpr上の関数)
  • 13.
    例 ● auto f = METAEXPR_FUN((p0 x, p1 y)->decltype( f(x, g(y)) )); ● auto f = fun_t<auto (p0 x, p1 y)->decltype( f(x, g(y)) )>();
  • 14.
    パターンマッチ ● match(value) | when<pattern>(expr) | … ● valueがpatternと同じ構造であれば、 (pattern内で/その外側で)束縛された変数で exprを評価する。そうでなければ次のwhen節 を試す ● 最後のwhen節でマッチできなければエラー
  • 15.
    例 ● auto f = METAEXPR_FUN((p0 x) -> decltype( match(x) | when<type_t<p0 &> > (METAEXPR_VALUEOF(p0 const &)) // a) xがT const &だったらT | when<f<p0, p1> >(METAEXPR_VALUEOF(f<p1, p0>)) // xがf<T, U>だったらf<U, T> | when<_>(METAEXPR_VALUEOF(int))); // xによらずint ● p0とかp1は、その位置に対応する型に束縛される。例え ばxがみたいな型だった場合、(a)のexpr内のp0はintに 置き換えられる ● _は何にでもマッチする
  • 16.
    今後の課題 ● 実装のほうは思いつきで作り始めたままなので 色々おかしい、というかまだ実装途中 (remove_const作っても動かないし高階関数は使 えない、再帰関数を定義できない、など) ● クラステンプレートによるメタ関数みたいに特 殊化でAd-hocに挙動変更とかはできないのを なんとかする
  • 17.
    参考 ● http://svn.boost.org/svn/boost/ sandbox/ftmpl/