SlideShare a Scribd company logo
λ expression for PP
を作ってみました
digitalghost
http://d.hatena.ne.jp/DigitalGhost/
http://twitter.com/DecimalBloat
自己紹介
●きりんさんがすきです。
でもC++のほうがもーっとすきです。
●プリプロセッサで遊んでます
●実は仕事でC++を使ったことは一度もない
●他の方の発表見てから資料作成余裕でした
今日の話
1.前提
2.この発表に説得力を付ける努力
1.どーきらしきもの
2.簡単な例
3.使い方
1.基本
2.構文糖
4.実用例
1.BOOST_PP_REPEATで
5.その他の話
1.ChaosPreprocessor
2.中途半端に形式的な文法
3.今回のブツ
4.ありがとう
前提
前提
●ラムダ式をなんとなく知っている
前提
●ラムダ式をなんとなく知っている
●Boost.Preprocessorのお世話になったことが
ある
前提
●ラムダ式をなんとなく知っている
●Boost.Preprocessorのお世話になったことが
ある
●BOOST_PP_ADD相当の機能が作れる
(もちろんプリプロセッサで)
この発表に説得力を
付ける努力
どーきらしきもの
●こんなことありませんか?
どーきらしきもの
●こんなことありませんか?
●BOOST_PP_REPEATを使うときステップごとの展
開用マクロをいちいち定義するのめんどくさい
どーきらしきもの
●こんなことありませんか?
●BOOST_PP_REPEATを使うときステップごとの展
開用マクロをいちいち定義するのめんどくさい
●引数がtupleのとき全要素にアクセスするためマクロ
を二段構えにするのめんどくさい
どーきらしきもの
●こんなことありませんか?
●BOOST_PP_REPEATを使うときステップごとの展
開用マクロをいちいち定義するのめんどくさい
●引数がtupleのとき全要素にアクセスするためマクロ
を二段構えにするのめんどくさい
※なければ何の役にも立たない話なので適当に時
間を潰してください。
どーきらしきもの
例:void fun0() 〜 void fun9()のfowarding
declarationを作る
どーきらしきもの
例:void fun0() 〜 void fun9()のfowarding
declarationを作る
#define FWD_DECL(z, n, d) 
void BOOST_PP_CAT(d, n)();
BOOST_PP_REPEAT(10, FWD_DECL, fun)
どーきらしきもの
例:void fun0() 〜 void fun9()のfowarding
declarationを作る
#define FWD_DECL(z, n, d) 
void BOOST_PP_CAT(d, n)();
BOOST_PP_REPEAT(10, FWD_DECL, fun)
展開結果
void f0();
void f1();
…
void f9();
どーきらしきもの
例:void fun0() 〜 void fun9()のfowarding
declarationを作る
#define FWD_DECL(z, n, d) 
void BOOST_PP_CAT(d, n)();
BOOST_PP_REPEAT(10, FWD_DECL, fun)
この#define FWD_DECLを定義するのが嫌だ
展開結果
void f0();
void f1();
…
void f9();
どーきらしきもの
例:void fun0() 〜 void fun9()のfowarding
declarationを作る
#define FWD_DECL(z, n, d) 
void BOOST_PP_CAT(d, n)();
BOOST_PP_REPEAT(10, FWD_DECL, fun)
この#define FWD_DECLを定義するのが嫌だ
ラムダ式使えればいいんじゃね?
展開結果
void f0();
void f1();
…
void f9();
どーきらしきもの
例:void fun0() 〜 void fun9()のfowarding
declarationを作る
#define FWD_DECL(z, n, d) 
void BOOST_PP_CAT(d, n)();
BOOST_PP_REPEAT(10, FWD_DECL, fun)
この#define FWD_DECLを定義するのが嫌だ
ラムダ式使えればいいんじゃね?
作ってみました
展開結果
void f0();
void f1();
…
void f9();
どーきらしきもの
例:void fun0() 〜 void fun9()のfowarding
declarationを作る
#define FWD_DECL(z, n, d) 
void BOOST_PP_CAT(d, n)();
BOOST_PP_REPEAT(10, FWD_DECL, fun)
この#define FWD_DECLを定義するのが嫌だ
ラムダ式使えればいいんじゃね?
作ってみました
●http://patch-tag.com/r/digitalghost/pplambda/home
展開結果
void f0();
void f1();
…
void f9();
簡単な例
さっきのfun0〜fun9をラムダ式で
簡単な例
さっきのfun0〜fun9をラムダ式で
BOOST_PP_REPEAT(10, PP_LAMBDA_EVAL_Z,
(LAMBDA3 (void)
APPLY2(BOOST_PP_CAT)(3_, 2_)
(();),
fun))
簡単な例
さっきのfun0〜fun9をラムダ式で
BOOST_PP_REPEAT(10, PP_LAMBDA_EVAL_Z,
(LAMBDA3 (void)
APPLY2(BOOST_PP_CAT)(3_, 2_)
(();),
fun))
●PP_LAMBDA_EVAL_Zはラムダ式の評価器
簡単な例
さっきのfun0〜fun9をラムダ式で
BOOST_PP_REPEAT(10, PP_LAMBDA_EVAL_Z,
(LAMBDA3 (void)
APPLY2(BOOST_PP_CAT)(3_, 2_)
(();),
fun))
●PP_LAMBDA_EVAL_Zはラムダ式の評価器
●LAMBDA3から(();)までがラムダ式本体
簡単な例
さっきのfun0〜fun9をラムダ式で
BOOST_PP_REPEAT(10, PP_LAMBDA_EVAL_Z,
(LAMBDA3 (void)
APPLY2(BOOST_PP_CAT)(3_, 2_)
(();),
fun))
●PP_LAMBDA_EVAL_Zはラムダ式の評価器
●LAMBDA3から(();)までがラムダ式本体
●#defineとか最初からいらんかったんや!
使い方
基本1
PP_EVAL_LAMBDA(
LAMBDA2
(BOOST_PP_CAT) LPAREN ARG1 COMMA ARG2 RPAREN,
(Azniyan, Kawaiinar))
基本1
PP_EVAL_LAMBDA(
LAMBDA2
(BOOST_PP_CAT) LPAREN ARG1 COMMA ARG2 RPAREN,
(Azniyan, Kawaiinar))
●PP_EVAL_LAMBDA(expr, params)はラムダ式
の評価器
基本1
PP_EVAL_LAMBDA(
LAMBDA2
(BOOST_PP_CAT) LPAREN ARG1 COMMA ARG2 RPAREN,
(Azniyan, Kawaiinar))
●PP_EVAL_LAMBDA(expr, params)はラムダ式
の評価器
●第一引数がラムダ式
基本1
PP_EVAL_LAMBDA(
LAMBDA2
(BOOST_PP_CAT) LPAREN ARG1 COMMA ARG2 RPAREN,
(Azniyan, Kawaiinar))
●PP_EVAL_LAMBDA(expr, params)はラムダ式
の評価器
●第一引数がラムダ式
●第二引数はラムダ式の引数
展開すると
PP_EVAL_LAMBDA(
LAMBDA2
(BOOST_PP_CAT) LPAREN ARG1 COMMA ARG2 RPAREN,
(Azniyan, Kawaiinar))
展開すると
PP_EVAL_LAMBDA(
LAMBDA2
(BOOST_PP_CAT) LPAREN ARG1 COMMA ARG2 RPAREN,
(Azniyan, Kawaiinar))
↓
BOOST_PP_CAT ( Azniyan , Kawaiinar )
展開すると
PP_EVAL_LAMBDA(
LAMBDA2
(BOOST_PP_CAT) LPAREN ARG1 COMMA ARG2 RPAREN,
(Azniyan, Kawaiinar))
↓
BOOST_PP_CAT ( Azniyan , Kawaiinar )
↓
AzniyanKawaiinar
展開すると
PP_EVAL_LAMBDA(
LAMBDA2
(BOOST_PP_CAT) LPAREN ARG1 COMMA ARG2 RPAREN,
(Azniyan, Kawaiinar))
↓
BOOST_PP_CAT ( Azniyan , Kawaiinar )
↓
AzniyanKawaiinar
※http://twitter.com/azniyan
基本2
●LAMBDAnは「n引数のラムダ式」という意味
(nは1〜3)
●以下のルール
●(hoge) → hoge
●LPAREN → (
●RPAREN → )
●COMMA → ,
●ARGn → ラムダ式のn個目の引数
の組み合わせ(nは1〜3)
もう一度あずにやんかわいいなあ
PP_EVAL_LAMBDA(
LAMBDA2
(BOOST_PP_CAT) LPAREN ARG1 COMMA ARG2 RPAREN,
(Azniyan, Kawaiinar))
↓
BOOST_PP_CAT ( Azniyan , Kawaiinar )
↓
AzniyanKawaiinar
もう一度あずにやんかわいいなあ
PP_EVAL_LAMBDA(
LAMBDA2
(BOOST_PP_CAT) LPAREN ARG1 COMMA ARG2 RPAREN,
(Azniyan, Kawaiinar))
↓
BOOST_PP_CAT ( Azniyan , Kawaiinar )
↓
AzniyanKawaiinar
LPARENやRPARENを
並べた結果が
マクロ呼び出しの形なら
それも展開される
LPARENとか書くのめんどくさい…
LPARENとか書くのめんどくさい…
●構文糖あります
LPARENとか書くのめんどくさい…
●構文糖あります
●APPLYn(f)(expr1, expr2, …)
= (f) LPAREN expr1 COMMA expr2 COMMA …
RPAREN
LPARENとか書くのめんどくさい…
●構文糖あります
●APPLYn(f)(expr1, expr2, …)
= (f) LPAREN expr1 COMMA expr2 COMMA …
RPAREN
●n(expr1, expr2, …)
= LPAREN expr1 COMMA expr2 COMMA …
RPAREN
LPARENとか書くのめんどくさい…
●構文糖あります
●APPLYn(f)(expr1, expr2, …)
= (f) LPAREN expr1 COMMA expr2 COMMA …
RPAREN
●n(expr1, expr2, …)
= LPAREN expr1 COMMA expr2 COMMA …
RPAREN
※ただしnは1〜3
あずにやん with 構文糖
PP_EVAL_LAMBDA(
LAMBDA2
(BOOST_PP_CAT) LPAREN ARG1 COMMA ARG2 RPAREN,
(Azniyan, Kawaiinar))
あずにやん with 構文糖
PP_EVAL_LAMBDA(
LAMBDA2
(BOOST_PP_CAT) LPAREN ARG1 COMMA ARG2 RPAREN,
(Azniyan, Kawaiinar))
は、こう書き換えられる
あずにやん with 構文糖
PP_EVAL_LAMBDA(
LAMBDA2
(BOOST_PP_CAT) LPAREN ARG1 COMMA ARG2 RPAREN,
(Azniyan, Kawaiinar))
は、こう書き換えられる
PP_EVAL_LAMBDA(
LAMBDA2
APPLY2(BOOST_PP_CAT) (ARG1, ARG2),
(Azniyan, Kawaiinar))
あずにやん with 構文糖
PP_EVAL_LAMBDA(
LAMBDA2
(BOOST_PP_CAT) LPAREN ARG1 COMMA ARG2 RPAREN,
(Azniyan, Kawaiinar))
こうも書き変えられる
PP_EVAL_LAMBDA(
LAMBDA2
(BOOST_PP_CAT) 2(ARG1, ARG2),
(Azniyan, Kawaiinar))
●APPLYを使うより短く書けるけど見た目がキモ
い
実用例
BOOST_PP_REPEATで
●導入で登場した例
BOOST_PP_REPEAT(10, PP_LAMBDA_EVAL_Z,
(LAMBDA3 (void)
APPLY2(BOOST_PP_CAT)(3_, 2_)
(();),
fun))
BOOST_PP_REPEATで
●導入で登場した例
BOOST_PP_REPEAT(10, PP_LAMBDA_EVAL_Z,
(LAMBDA3 (void)
APPLY2(BOOST_PP_CAT)(3_, 2_)
(();),
fun))
●ポイントは PP_LAMBDA_EVAL_Z
PP_LAMBDA_EVAL_Z
●ラムダ式で繰り返しを書くときに使う、EVALの
ラッパ
PP_LAMBDA_EVAL_Z
●ラムダ式で繰り返しを書くときに使う、EVALの
ラッパ
●「Z」はBOOST_PP_REPEATの繰り返し用関数
マクロの一つ目の引数に由来
PP_LAMBDA_EVAL_Z
●ラムダ式で繰り返しを書くときに使う、EVALの
ラッパ
●「Z」はBOOST_PP_REPEATの繰り返し用関数
マクロの一つ目の引数に由来
●BOOST_PP_REPEAT_FROM_TO や、
BOOST_PP_ENUMでもこのマクロを使えます
PP_LAMBDA_EVAL_Z
●ラムダ式で繰り返しを書くときに使う、EVALの
ラッパ
●「Z」はBOOST_PP_REPEATの繰り返し用関数
マクロの一つ目の引数に由来
●BOOST_PP_REPEAT_FROM_TO や、
BOOST_PP_ENUMでもこのマクロを使えます
●マジンガーもドラゴンボールも関係ないです
PP_LAMBDA_EVAL_Z
#define FWD_DECL(z, n, d) 
void BOOST_PP_CAT(d, n)();
BOOST_PP_REPEAT(10, FWD_DECL,
fun)
PP_LAMBDA_EVAL_Z
#define FWD_DECL(z, n, d) 
void BOOST_PP_CAT(d, n)();
BOOST_PP_REPEAT(10, FWD_DECL,
fun)
BOOST_PP_REPEAT(10, PP_LAMBDA_EVAL_Z,
(LAMBDA3 (void)
APPLY2(BOOST_PP_CAT)(3_, 2_)
(();),
fun))
PP_LAMBDA_EVAL_Z
#define FWD_DECL(z, n, d) 
void BOOST_PP_CAT(d, n)();
BOOST_PP_REPEAT(10, FWD_DECL,
fun)
BOOST_PP_REPEAT(10, PP_LAMBDA_EVAL_Z,
(LAMBDA3 (void)
APPLY2(BOOST_PP_CAT)(3_, 2_)
(();),
fun))
PP_LAMBDA_EVAL_Z
#define FWD_DECL(z, n, d) 
void BOOST_PP_CAT(d, n)();
BOOST_PP_REPEAT(10, FWD_DECL,
fun)
BOOST_PP_REPEAT(10, PP_LAMBDA_EVAL_Z,
(LAMBDA3 (void)
APPLY2(BOOST_PP_CAT)(3_, 2_)
(();),
fun))
繰り返し用マクロを
EVAL_Zに変更
PP_LAMBDA_EVAL_Z
#define FWD_DECL(z, n, d) 
void BOOST_PP_CAT(d, n)();
BOOST_PP_REPEAT(10, FWD_DECL,
fun)
BOOST_PP_REPEAT(10, PP_LAMBDA_EVAL_Z,
(LAMBDA3 (void)
APPLY2(BOOST_PP_CAT)(3_, 2_)
(();),
fun))
繰り返し用マクロを
EVAL_Zに変更
PP_LAMBDA_EVAL_Z
#define FWD_DECL(z, n, d) 
void BOOST_PP_CAT(d, n)();
BOOST_PP_REPEAT(10, FWD_DECL,
fun)
BOOST_PP_REPEAT(10, PP_LAMBDA_EVAL_Z,
(LAMBDA3 (void)
APPLY2(BOOST_PP_CAT)(3_, 2_)
(();),
fun))
繰り返し用マクロを
EVAL_Zに変更
三つ目の引数を
ラムダ式と繰り返しマクロの引数
のタプルにする
その他の話
Chaos Preprocessor
Chaos Preprocessor
●http://sourceforge.net/projects/chaos-pp/
Chaos Preprocessor
●http://sourceforge.net/projects/chaos-pp/
●Boost.PPの作者によるプリプロセッサメタプロ
グラミングライブラリ
例:Active Argument
●ドキュメントの一番最初に紹介されている機能
例:Active Argument
●ドキュメントの一番最初に紹介されている機能
#define A(n) 
CHAOS_PP_DEFER(A_INDIRECT)()(CHAOS_PP_INC(n)) 
/**/
#define A_INDIRECT() A
#define X(arg) arg
#define Y(arg) X(arg)
#define Z(arg) Y(arg)
A(0) // A_INDIRECT()(1)
X( A(0) ) // A_INDIRECT()(2)
Y( A(0) ) // A_INDIRECT()(3)
Z( A(0) ) // A_INDIRECT()(4)
例:Active Argument
●ドキュメントの一番最初に紹介されている機能
#define A(n) 
CHAOS_PP_DEFER(A_INDIRECT)()(CHAOS_PP_INC(n)) 
/**/
#define A_INDIRECT() A
#define X(arg) arg
#define Y(arg) X(arg)
#define Z(arg) Y(arg)
A(0) // A_INDIRECT()(1)
X( A(0) ) // A_INDIRECT()(2)
Y( A(0) ) // A_INDIRECT()(3)
Z( A(0) ) // A_INDIRECT()(4)
●どう使うんだろう…
中途半端に形式的な文法
pp-lambda:
LAMBDA n pp-lambda-expr
pp-lambda-expr:
pp-lambda-term
pp-lambda-expr pp-lambda-term
pp-lambda-term:
pp-lambda-literal
pp-lambda-parameter
pp-lambda-macro-call
COMMA
LPAREN
RPAREN
pp-lambda-tuple
pp-lambda-macro-call:
APPLY n ( balanced-pp-tokens ) ( pp-lambda-expr-list )
pp-lambda-expr-list:
pp-lambda-expr
pp-lambda-expr-list , pp-lambda-expr
pp-lambda-parameter:
digit underscore
pp-lambda-literal:
( balanced-pp-tokens )
pp-lambda-tuple:
digit ( pp-lambda-expr-list )
underscore:
直前に空白文字がない _
n:
直前に空白文字がない digit
今回のブツ
●http://patch-tag.com/r/digitalghost/pplambda/home
●darcs get http://patch-tag.com/r/digitalghost/pplambda
●http://sites.google.com/site/ilikemanaka/code/pplambda.tar.bz2
ありがとう
●kothaさん
●http://www.kotha.net/
●アドバイスなどいただきました
終わり

More Related Content

PPTX
Boost.python
PPTX
ナウなヤングにバカうけのイカしたタグ付き共用体
PDF
拡張可能でprintfっぽい書式指定ができて書式指定文字列と引数をコンパイル時に検証できる文字列フォーマット関数を作った
PDF
Define and expansion of cpp macro
PDF
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
PDF
君はまだ,本当のプリプロセスを知らない
PDF
C++コンパイラ GCCとClangからのメッセージをお読みください
PDF
No skk, no life.
Boost.python
ナウなヤングにバカうけのイカしたタグ付き共用体
拡張可能でprintfっぽい書式指定ができて書式指定文字列と引数をコンパイル時に検証できる文字列フォーマット関数を作った
Define and expansion of cpp macro
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
君はまだ,本当のプリプロセスを知らない
C++コンパイラ GCCとClangからのメッセージをお読みください
No skk, no life.
Ad

Preprocess-time Lambda Expression