C++ Template Meta Programming の紹介@社内勉強会
Upcoming SlideShare
Loading in...5
×
 

C++ Template Meta Programming の紹介@社内勉強会

on

  • 2,691 views

 

Statistics

Views

Total Views
2,691
Views on SlideShare
2,689
Embed Views
2

Actions

Likes
3
Downloads
18
Comments
0

1 Embed 2

https://twitter.com 2

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

C++ Template Meta Programming の紹介@社内勉強会 C++ Template Meta Programming の紹介@社内勉強会 Presentation Transcript

  • C++ Template Meta Programming の、さわりだけ... CORE 北海道カンパニー 勉強会 2013/7/26 松浦 13年7月27日土曜日
  • C++テンプレートを使ったメタプロ グラミングについて紹介します! まあ、そんなのもあるんだー、ふー ん、くらいな感じで 今日は、 13年7月27日土曜日
  • 13年7月27日土曜日 View slide
  • メタプログラムとは何か? テンプレートの基礎 テンプレート特殊化 再帰テンプレート メタ関数 型シーケンス さいごに 目次 13年7月27日土曜日 View slide
  • メタプログラムとは何か? テンプレートの基礎 テンプレート特殊化 再帰テンプレート メタ関数 型シーケンス さいごに 13年7月27日土曜日
  • ロジックを直接コーディングするの ではなく、あるパターンをもったロ ジックを生成する高位ロジックによ ってプログラミングを行う方法、ま たその高位ロジックを定義する方法 のこと。........wikipedia 13年7月27日土曜日
  • いみが まったくわからない いやん♡ 13年7月27日土曜日
  • プログラムを生成する プログラム、ってことで いいと思うぽよ。 ようは 13年7月27日土曜日
  • 例えばYACC expression : term | expression ‘+’ term {$$=$1+$2;} | expression ‘-’ term {$$=$1-$2;} ; term : factor | term ‘*’ factor { $$ = $1 * $2; } | term ‘/’ factor { $$ = $1 / $2; } ; factor : INTEGER | group ; group : ‘(’ expression ‘)’ ; 13年7月27日土曜日
  • YACC .y YACC .c 13年7月27日土曜日
  • YACC .y YACC .c ドメイン言語 (DSL) ホスト言語 13年7月27日土曜日
  • boost.spirit expr = ( term[expr.val = _1] >> '+' >> expr[expr.val += _1]) | ( term[expr.val = _1] >> '-' >> expr[expr.val -= _1]) | term[expr.val = _1] ; term = ( factor[term.val = _1] >> '*' >> term[term.val *= _1]) | ( factor[term.val = _1] >> '/' >> term[term.val /= _1]) | factor[term.val = _1] ; factor = integer[factor.val = _1] | ( '(' >> expr[factor.val- _1] >> ')' ) ; 13年7月27日土曜日
  • boost.spirit .cpp 13年7月27日土曜日
  • boost.spirit .cppドメイン言語 ホスト言語 13年7月27日土曜日
  • boost.spirit .cppドメイン言語 ホスト言語 EDSL(埋め込みドメイン言語) 13年7月27日土曜日
  • boost.spirit .cppドメイン言語 ホスト言語 EDSL(埋め込みドメイン言語) YACC相当のものは? 13年7月27日土曜日
  • boost.spirit .cppドメイン言語 ホスト言語 EDSL(埋め込みドメイン言語) YACC相当のものは? テンプレート・メタプログラミング 13年7月27日土曜日
  • なぜC++でメタプロ? 別の構文規則を学ぶ必要がない 他のメタプロとの相互運用 余分な構築ステップ不要 品質、再利用、可搬性 13年7月27日土曜日
  • とはいえ boost.spiritのような究極のメタプロ グラミングの話は割愛します。 このあとの章では、C++メタプロを 支える基本的な部分だけお話します。 (ちゃんと話せる自信がないというのはナイショぽよ 13年7月27日土曜日
  • メタプログラムとは何か? テンプレートの基礎 テンプレート特殊化 再帰テンプレート メタ関数 型シーケンス さいごに 13年7月27日土曜日
  • 普通のジェネリック // C# List<string> list = new List<string>(); list.add("hoge"); list.add("page"); // Java List<String> list = new ArrayList<String>(); list.add("hoge"); list.add("page"); //C++ list<string> list; list.insert("hoge"); list.insert("page"); 13年7月27日土曜日
  • 非型テンプレート //C++ template<int N> struct pow { static const int value = N*N; }; int n = pow<3>::value; // n = 3*3; 13年7月27日土曜日
  • 型の操作 ポインタを追加する //C++ template<class T> struct add_pointer { typedef T* type; }; int n = 10; // int* p = &n; add_pointer<int>::type p = &n; 13年7月27日土曜日
  • C++テンプレート コンパイル時に計算してしまう(実行 時コスト0)。 非型テンプレート 型操作 .....などなど 13年7月27日土曜日
  • メタプログラムとは何か? テンプレートの基礎 テンプレート特殊化 再帰テンプレート メタ関数 型シーケンス さいごに 13年7月27日土曜日
  • add_pointerの例 ん?? // int* p = &n; add_pointer<int>::type p1 = &n; // これはエラー:int** p2 = &n; add_pointer<int*>::type p2 = &n; 13年7月27日土曜日
  • そこで特殊化 template<class T> struct add_pointer { typedef T* type; }; // そもそもポインタだったらこっち template<class T> struct add_pointer<T*> { typedef T* type; }; int n = 10; // int* p = &n; add_pointer<int>::type p1 = &n; // めでたし add_pointer<int*>::type p2 = &n; 13年7月27日土曜日
  • テンプレート特殊化 テンプレート特殊化により、 コンパイル時に条件分岐を行 うことができる。 13年7月27日土曜日
  • コンパイル時 if文 template<bool b, class T1, class T2> struct If_; template<class T1, class T2> struct If_<true,T1,T2> { typedef T1 type; // 条件が真ならT1を使用する }; template<class T1, class T2> struct If_<false,T1,T2> { typedef T2 type; // 条件が偽ならT2を使用する }; If_<sizeof(long) > sizeof(char), char, long>::type x; // char x; 13年7月27日土曜日
  • コンパイル時assert // 宣言だけ template<bool b> struct Static_assert; // true版のみ定義しfalse版は定義しない template<> struct Static_assert<true>{}; #define STATIC_ASSERT(b) { sizeof( Static_assert<b> ); } void foo() { STATIC_ASSERT(sizeof(long) == 4); char dest[32]; char src[16]; STATIC_ASSERT(sizeof(dest) >= sizeof(src)); ::memcpy(dest,src,sizeof(src)); } 13年7月27日土曜日
  • C++テンプレート コンパイル時に計算してしまう(実行 時コスト0)。 非型テンプレート 型操作 特殊化による条件分岐 13年7月27日土曜日
  • メタプログラムとは何か? テンプレートの基礎 テンプレート特殊化 再帰テンプレート メタ関数 型シーケンス さいごに 13年7月27日土曜日
  • 普通に再帰で階乗計算 int factorial(int N) { return N==0 ? 1 : N*factorial(N-1); } int n = factorial(3); // 6 13年7月27日土曜日
  • 再帰テンプレートで // 階乗を求める template <int N> struct factorial_t { static const int value = N*factorial_t<N-1>::value; }; // N==0の場合は特殊化する template <> struct factorial_t<0> { static const int value = 1; }; int n2 = factorial_t<3>::value; // n2 = 6; 13年7月27日土曜日
  • 再帰テンプレート 再帰テンプレートにより、コ ンパイル時に繰り返し処理を 行うことができる。 13年7月27日土曜日
  • 余談 C++テンプレートはチューリング 完全である(制限:再帰に限界あり) C++ Templates are Turing Complete http://ubietylab.net/ubigraph/content/ Papers/pdf/CppTuring.pdf 13年7月27日土曜日
  • C++テンプレート コンパイル時に計算してしまう(実行時コ スト0)。 非型テンプレート 型操作 特殊化による条件分岐 再帰テンプレートによる繰り返し 13年7月27日土曜日
  • このへんから ちょっとだけ応用な感じです。 ちょっとだけよ♡ 13年7月27日土曜日
  • メタプログラムとは何か? テンプレートの基礎 テンプレート特殊化 再帰テンプレート メタ関数 型シーケンス さいごに 13年7月27日土曜日
  • メタ関数とは add_pointer<int>::type pi; 関数名 int v = factorial_t<3>::value; パラメータ 戻り値(型) 関数名 パラメータ 戻り値(値) 13年7月27日土曜日
  • 高階関数を考えてみよう まずは普通のテンプレート関数 f(f(x)) の結果を返すtwice template<class F, class X> struct twice { static int value(const X& x ){ return F::apply(F::apply(x)); } }; struct div2 { static int apply(int x) { return x/2; } }; std::cout << twice<div2,int>::value(8); // 2 13年7月27日土曜日
  • 高階メタ関数 template<class F, int N> struct twice { static const int value = F::template apply< F::template apply<N>::value >::value; }; struct div2 { template<int N> struct apply { static const int value = N/2; }; }; std::cout << twice<div2,8>::value; // 2 13年7月27日土曜日
  • メタプログラムとは何か? テンプレートの基礎 テンプレート特殊化 再帰テンプレート メタ関数 型シーケンス さいごに 13年7月27日土曜日
  • こんなことしたい それぞれの型のインスタンスを用意してメソ ッドを呼び出したい。 struct A { std::string name() const { return "A!"; } }; struct B { std::string name() const { return "B!"; } }; struct C { std::string name() const { return "C!"; } }; struct D { std::string name() const { return "D!"; } }; /* こんなことしたい A a; a.name(); B b; b.name(); C c; c.name(); D d; d.name(); とか for( v : [A,B,C,D] ) print( v.name() ); // 擬似コードです */ 13年7月27日土曜日
  • JavaやC#、ObjC あたりのアプローチ リフレクションを使う。 Classクラスのようなメタクラスの配 列を使って動的生成する、とかね。 C++のリフレクションは貧弱。 どうしよう。 13年7月27日土曜日
  • C++のアプローチ メタプログラミングで型のリスト(型シーケ ンス)を用意し、各型にアクセスする仕掛け を考えてみる。 TypeList<A,B,C,D>::type; 13年7月27日土曜日
  • C++のアプローチ メタプログラミングで型のリスト(型シーケ ンス)を用意し、各型にアクセスする仕掛け を考えてみる。 TypeList<A,B,C,D>::type; このへんをどうするか?? 13年7月27日土曜日
  • 型シーケンス template<class First, class Rest> struct Cons { typedef First first; typedef Rest rest; }; struct ConsNil {}; // 型シーケンス TypeList<T1,T2,T3,T4> template<class T1, class T2, class T3, class T4> struct TypeList { typedef Cons<T1,Cons<T2,Cons<T3,Cons<T4,ConsNil> > > > type; }; 13年7月27日土曜日
  • 型シーケンス template<class First, class Rest> struct Cons { typedef First first; typedef Rest rest; }; struct ConsNil {}; // 型シーケンス TypeList<T1,T2,T3,T4> template<class T1, class T2, class T3, class T4> struct TypeList { typedef Cons<T1,Cons<T2,Cons<T3,Cons<T4,ConsNil> > > > type; }; このへんがキモ 13年7月27日土曜日
  • むずくないよ template<class First, class Rest> struct Cons { typedef First first; typedef Rest rest; }; struct ConsNil {}; template<class T1, class T2, class T3, class T4> struct TypeList { typedef Cons<T1,Cons<T2,Cons<T3,Cons<T4,ConsNil> > > > type; }; // typedef First first; : T1 // typedef Rest rest; : Cons<T2,Cons<T3,Cons<T4,ConsNil> > > // typedef First first; : T2 // typedef Rest rest; : Cons<T3,Cons<T4,ConsNil> > // typedef First first; : T3 // typedef Rest rest; : Cons<T4,ConsNil> // typedef First first; : T4 // typedef Rest rest; : ConsNil ← ターミネータ 13年7月27日土曜日
  • あとは繰り返す処理 // typedef First first; : T1 // typedef Rest rest; : Cons<T2,Cons<T3,Cons<T4,ConsNil> > > // typedef First first; : T2 // typedef Rest rest; : Cons<T3,Cons<T4,ConsNil> > // typedef First first; : T3 // typedef Rest rest; : Cons<T4,ConsNil> // typedef First first; : T4 // typedef Rest rest; : ConsNil ← ターミネータ template<class CONS> struct for_each { template<class FUNC> static void apply( const FUNC& f ) { typename CONS::first v; f( v ); for_each<typename CONS::rest>::apply(f); } }; 13年7月27日土曜日
  • ターミネータ忘れてた! template<class CONS> struct for_each { template<class FUNC> static void apply( const FUNC& f ) { typename CONS::first v; f( v ); for_each<typename CONS::rest>::apply(f); } }; // ターミネータ用に特殊化 template<> struct for_each<ConsNil> { template<class FUNC> static void apply( const FUNC& ){ } }; 13年7月27日土曜日
  • 使ってみよう struct A { std::string name() const { return "A!"; } }; struct B { std::string name() const { return "B!"; } }; struct C { std::string name() const { return "C!"; } }; struct D { std::string name() const { return "D!"; } }; struct Printer { template<class T> void operator()(const T& v) const { std::cout << v.name() << std::endl; } }; void foo() { for_each<TypeList<A,B,C,D>::type>::apply( Printer() ); } // for( v : [A,B,C,D] ) print( v.name() ); ↑ 似てる // A! // B! // C! // D! 13年7月27日土曜日
  • リフレクションが無くても テンプレートでいろいろ出来ちゃう。 しかも多くをコンパイル時に静的に。 boost.mpl には型のためのコンテナ、 イテレータ、アルゴリズムがある。遅 延評価、ラムダなども。正直、あたまおかしい(笑) 13年7月27日土曜日
  • メタプログラムとは何か? テンプレートの基礎 テンプレート特殊化 再帰テンプレート メタ関数 型シーケンス さいごに 13年7月27日土曜日
  • 新たなパラダイムに出会えたね! 構造化 データ指向 オブジェクト指向 ジェネリック 関数型 ・・・ メタプログラミング 13年7月27日土曜日
  • 余談 GoFデザインパターンはオブジェクト指向だ けか? 例えば Abstract FactoryパターンやVisitor パタ ーンは、メタプロと相性が良い。 継承でなくポリシとか。 メタプロと関数型? どちらも状態を持たない 13年7月27日土曜日
  • まとめ C++テンプレート機能により、コン パイル時の処理を書くことが出来る。 ライブラリの実装では多用される。 でも、正直読みにくいし難解。 C++11ではconstexprにより多少ましになっている。 13年7月27日土曜日
  • おつかれさま! もうおわり?♡ ふう... 13年7月27日土曜日