Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Introduce to CPP ~黒魔術へのいざない~

312 views

Published on

Jikai Lightning Talk#1 で発表しました。

Published in: Engineering
  • Be the first to comment

  • Be the first to like this

Introduce to CPP ~黒魔術へのいざない~

  1. 1. CAUTION この発表は黒魔術要素が多く含まれています。 内容はあまり真に受けず、 プロダクトコードには用法・用量をよく守って お使いください。
  2. 2. Intoroduce to CPP ~黒魔術へのいざない~ 2018/06/19 Mixi Jikai Lightning Talks #1 @reanisz__
  3. 3. C++3つの世界 テンプレート 世界 プリプロセス 世界 コンパイルされたものを実行したときの世界。 チューリング完全。 コンパイル時にテンプレートを解決する世界。 チューリング完全。 コンパイル前にソースファイルを処理する世界。 (※条件付きで)チューリング完全。 実行時 世界 (人間界) ※プリプロセッサ自体をループ内で実行したとき
  4. 4. もっと プリプロセス世界も 使いこなすべき! ※個人の感想であり、効果・効能を示すものではありません。
  5. 5. マクロおさらい #define HOGE AAAAAA HOGE // AAAAAA に置換される #define FUNC(a, b) a b a FUNC(X, Y) // X Y X に置換される #define CAT(a, b) a ## b CAT(X, Y) // トークン連結して XY に置換される #define STRINGIZE(a) #a STRINGIZE(HOGE) // 文字列化して"Hoge"に置換される #define FUNC2(a, ...) a __VA_ARGS__ a FUNC2(A, X, Y, Z) // A X, Y, Z A に置換される (可変長引数)
  6. 6. マクロは再帰できない #define Func(x) x(y) Func(Func) // => Func(y) // ここまで展開されるが、そこで止まる (再帰できない) (重要) // => y(y)
  7. 7. Enumの文字列化
  8. 8. こんなコードあるあるですよね enum Type{ Dog, Cat, Human, }; const char* getName(Type t){ switch(t){ case Dog: return "Dog"; case Cat: return "Cat"; case Human: return "Human"; } }
  9. 9. getNameを追加し忘れたら… enum Type{ Dog, Cat, Human, Dragon, }; const char* getName(Type t){ switch(t){ case Dog: return "Dog"; case Cat: return "Cat"; case Human: return "Human"; } }
  10. 10. プリプロセスで 自動生成しましょう!
  11. 11. CodeGen 完成形イメージ enum Type{ Dog, Cat, Human, }; const char* getName(Type t){ switch(t){ case Dog: return "Dog"; case Cat: return "Cat"; case Human: return "Human"; } } #define TYPES (Dog, Cat, Human) #define GEN_ENUM(v) v, enum Type{ FOR_EACH(GEN_ENUM, TYPES) }; #define GEN_FUNC(v) ¥ case v : return STRINGIZE(v); const char* getName(Type t){ switch(t){ FOR_EACH(GEN_FUNC, TYPES) } }
  12. 12. プリプロセスによるTuple (a) // 1要素のtuple (a, b) // 2要素のtuple (a, b, c) // 3要素のtuple
  13. 13. Tupleの要素数を得るマクロ #define TUPLE_SIZE_D(e0, e1, e2, e3, size, ...) size #define TUPLE_SIZE_I(...) TUPLE_SIZE_D(__VA_ARGS__, 4, 3, 2, 1) #define TUPLE_SIZE(tuple) TUPLE_SIZE_I tuple TUPLE_SIZE( (a, b, c) ) // => TUPLE_SIZE_I (a, b, c) // => TUPLE_SIZE_D (a, b, c, 4, 3, 2, 1) // => 3
  14. 14. Tupleの特定の要素を得る #define CAT(a, b) a ## b #define TUPLE_GET_0(e0, ...) e0 #define TUPLE_GET_1(e0, e1, ...) e1 #define TUPLE_GET_2(e0, e1, e2, ...) e2 #define TUPLE_GET_3(e0, e1, e2, e3, ...) e3 #define TUPLE_GET_I(i, tuple) CAT(TUPLE_GET_, i) tuple #define TUPLE_GET(i, tuple) TUPLE_GET_I(i, tuple) TUPLE_GET(1, (a, b)) // => TUPLE_GET_I(1, (a, b)) // => CAT(TUPLE_GET_, 1) (a, b) // => TUPLE_GET_1 (a, b) // => b
  15. 15. 繰り返す #define REPEAT_I4(f, p, n) REPEAT_I3(f, p, n) f( p (3) n ) #define REPEAT_I3(f, p, n) REPEAT_I2(f, p, n) f( p (2) n ) #define REPEAT_I2(f, p, n) REPEAT_I1(f, p, n) f( p (1) n ) #define REPEAT_I1(f, p, n) f( p (0) n ) #define REPEAT_I(i, f, p, n) CAT(REPEAT_I, i)(f, p, n) #define REPEAT(i, f, p, n) REPEAT_I(i, f, p, n) REPEAT(3, F, P, N) // => REPEAT_I(3, F, P, N) // => CAT(REPEAT_I, 3)(F, P, N) // => REPEAT_I3(F, P, N) // => REPEAT_I2(F, P, N) F( P (2) N ) // => REPEAT_I1(F, P, N) F( P (1) N ) F( P (2) N ) // => F( P (0) N ) F ( P (1) N ) F ( P (2) N )
  16. 16. Foreachを書く #define FOR_EACH_FUNC_I(i) CAT(TUPLE_GET_, i) #define FOR_EACH(tuple, func) ¥ REPEAT(TUPLE_SIZE(tuple), func, FOR_EACH_FUNC_I, tuple) FOR_EACH( (a, b, c), func ) // => REPEAT(TUPLE_SIZE((a, b, c)), func, FOR_EACH_FUNC_I, (a, b, c) // => REPEAT(3, func, FOR_EACH_FUNC_I, (a, b, c) // => func(FOR_EACH_FUNC_I (0) (a, b, c)) func(FOR_EACH_FUNC_I (1) (a, b, c)) func(FOR_EACH_FUNC_I (2) (a, b, c)) // => func(TUPLE_GET_0(a, b, c)) func(TUPLE_GET_1(a, b, c)) func(TUPLE_GET_2(a, b, c)) // => func(a) func(b) func(c)
  17. 17. 完成! #define TYPES (Dog, Cat, Human) #define GEN_ENUM(v) v, enum Type{ FOR_EACH(TYPES, GEN_ENUM) }; #define GEN_FUNC(v) case v : return STRINGIZE(v); const char* getName(Type t){ switch(t){ FOR_EACH(TYPES, GEN_FUNC) } }
  18. 18. 完成! #define TYPES (Dog, Cat, Human) #define GEN_ENUM(v) v, enum Type{ GEN_ENUM(Dog) GEN_ENUM(Cat) GEN_ENUM(Human) }; #define GEN_FUNC(v) case v : return STRINGIZE(v); const char* getName(Type t){ switch(t){ GEN_FUNC(Dog) GEN_FUNC(Cat) GEN_FUNC(Human) } } FOR_EACH( (a, b, c), func ) // => func(a) func(b) func(c)
  19. 19. 完成! #define TYPES (Dog, Cat, Human) #define GEN_ENUM(v) v, enum Type{ Dog, Cat, Human, }; #define GEN_FUNC(v) case v : return STRINGIZE(v); const char* getName(Type t){ switch(t){ case Dog: return "Dog"; case Cat: return "Cat"; case Human: return "Human"; } } GEN_ENUM(v) // => v, GEN_FUNC(v) // => case v: return “v”;
  20. 20. 人間向け (Boost.PP) #define TYPES (Dog)(Cat)(Human) #define GEN_ENUM(v) v, enum Type{ BOOST_PP_SEQ_FOR_EACH(GEN_ENUM, _, TYPES) }; #define GEN_FUNC(v) case v : return STRINGIZE(v); const char* getName(Type t){ switch(t){ BOOST_PP_SEQ_FOR_EACH(GEN_FUNC, _, TYPES) } }
  21. 21. 結論
  22. 22. 結論 Pythonでやれ
  23. 23. ご清聴 ありがとうございました

×