More Related Content Similar to 君はまだ,本当のプリプロセスを知らない Similar to 君はまだ,本当のプリプロセスを知らない (20) More from digitalghost (7) 君はまだ,本当のプリプロセスを知らない6. よくある事例
● “A:” >> qi::int_ % ','
| “B:” >> qi::int_ % ','
| “C:” >> qi::string
● 結果は variant<vector<int>, string> 相当
● しかし A: と B: の場合で区別したい
● variant<vector<int>, vector<int>,
string> になりませんか?
7. よくある事例
● struct player {
unsigned hp;
unsigned atk;
void attack(player & target) {
target.hp -= this->hp;
}
};
_人人人人人人_
> 体力勝負 <
 ̄Y^Y^Y^Y^Y ̄
11. お詫び
● 今 github に上がってるコードは gcc のバージョン上げたら
動かなくなってました☆(・ω<)
– マクロではなく TMP の部分でエラーになってるので C++ コンパ
イラ各位にはデバッグをお願いしたく
12. コード例
● std::vector<int> の begin と end メンバと全ての
コンストラクタのみを公開し,as_base という名前で元
の型の値として扱える ivector クラスの定義
● DESALT_NEWTYPE(ivector, std::vector<int>,
as_base,
begin,
end,
this
);
13. コード例
● std::basic_string<T> の機能のうち, append と
ostream への出力だけができる mystring 型
– (append は引数も戻り値も mystring 型)
● DESALT_NEWTYPE(mystring, std::string,
as_base,
this,
auto append,
namespace explicit (operator<<)
(std::ostream &, mystring const &)
);
16. 構文要素 this
● DESALT_NEWTYPE(hoge, fuga,
as_fuga,
piyo, // using fuga::piyo;
this // using fuga::fuga;
);
● this は Inheriting Ctor を使うための(このマクロに
とっての)キーワードで,つまり中で using
fuga::fuga; をしている
● どうなってるのか?
18. 構文要素 this
● DESALT_NEWTYPE(hoge, fuga,
as_fuga,
piyo, // using fuga::piyo;
this // using fuga::fuga;
);
● 先の方法で this 以外の未知のトークンも判定
できるので,知らないトークンだったらそのま
ま using する
19. 構文要素 auto
● struct fuga {
fuga piyo(int, fuga const &);
};
DESALT_NEWTYPE(hoge, fuga,
as_fuga,
auto piyo // hoge piyo(int x, hoge const & y) {
); // return piyo(x, y);
// }
● auto キーワードを使うと元の関数の引数と戻り値型を新しい型で置
き換えた関数を定義する(関係ない型はそのまま)
● これをするには auto piyo から piyo を取り出す必要がある
20. 構文要素 auto
● this の件でやった方法をそのまま流用
● #define KEYWORDauto ,
IS_EMPTY(BOOST_PP_TUPLE_ELEM(1,
(CAT(KEYWORD, auto piyo))))
● 要するに KEYWORD をくっ付けたら auto が消
えてカンマになるのでそれをタプルとして扱っ
て最初の要素(空トークン)を読み飛ばす
22. オンデマンド括弧
● トークン列の先頭に括弧があるかどうかを調べられたらよい
● #define IS_PAREN(...)
IS_PAREN_I(CAT(A, B __VA_ARGS__))
#define B(...) OK
#define AB 0,
#define AOK 1,
#define IS_PAREN_I(...)
IS_PAREN_II(__VA_ARGS__)
#define IS_PAREN_II(x, ...) x
● トークン列の前にテスト用の関数マクロを置くと,展開され
たときは OK に,されなかったときはそのまま残るの
で,this のときと同じ手法で判定すればよい
24. 空トークン
● Boost.PP の IS_EMPTY の実装
● #define IS_EMPTY(x)
IS_EMPTY_I(x A)
#define IS_EMPTY_I(y)
TUPLE_ELEM(2, 1, B ## y ())
#define A() , 0
#define BA() 1, 1 EMPTY
#define EMPTY()
27. 空トークン
● #define IS_EMPTY(...)
IF(IS_PAREN(__VA_ARGS__ ()),
IS_EMPTY_I,
0 TUPLE_EAT())(__VA_ARGS__)
#define IS_EMPTY_I(...)
IF(IS_PAREN(__VA_ARGS__),
0 TUPLE_EAT(),
IS_EMPTY_II)(__VA_ARGS__)
#define IS_EMPTY_II(...)
IS_PAREN(CAT(A, __VA_ARGS__) ())
#define A() ()
29. 空トークン
● A が 1 で B が 0 になるケースでは,次のどちらかになる
– 空
– 識別子っぽいもの
● IS_PAREN(CAT(A, __VA_ARGS__) ())
#define A() ()
● ここまでくるとトークン連結が使えるので,補助マクロを使っ
て,__VA_ARGS__ が空であれば () になるようにすれば判定
できる
32. このマクロを書いた人は
こんなマクロを書いています
● PPLambda
– #define で定義せずにマクロを作って適用する
– http://patch-tag.com/r/digitalghost/pplambda/home
● InitWithTuple
– std::tie みたいにタプルを使って複数の変数を初期化する
– https://github.com/dechimal/init-with-tuple
● AttoTest
– 自分用ユニットテストフレームワーク
– https://github.com/dechimal/atto-test
33. Special Thanks (アルファベット順)
● Cryolite さん
– 本日私の隣で同じく資料を作成する傍ら励ましをいただいた
● fadis_ さん
– LibreOfficeのダウンロードを手伝っていただいた
● Flast_RO さん
– LibreOfficeのダウンロードを手伝っていただいた
● melponn さん
– 無線LAN環境を貸していただいた
● ボレロさん,昼食で遅れたみなさん
– おかげで発表資料を書く時間をいただいた