c++ template meta programming の紹介@社内勉強会

59
C++ Template Meta Programming の、さわりだけ... CORE 北海道カンパニー 勉強会 2013/7/26 松浦 13727日土曜日

Upload: akihiko-matuura

Post on 31-May-2015

3.431 views

Category:

Technology


7 download

TRANSCRIPT

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

C++ Template MetaProgramming

の、さわりだけ...

CORE 北海道カンパニー 勉強会

2013/7/26 松浦

13年7月27日土曜日

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

C++テンプレートを使ったメタプログラミングについて紹介します!

まあ、そんなのもあるんだー、ふーん、くらいな感じで

今日は、

13年7月27日土曜日

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

13年7月27日土曜日

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

メタプログラムとは何か?テンプレートの基礎

テンプレート特殊化

再帰テンプレート

メタ関数

型シーケンスさいごに

目次

13年7月27日土曜日

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

メタプログラムとは何か?テンプレートの基礎

テンプレート特殊化

再帰テンプレート

メタ関数

型シーケンス

さいごに

13年7月27日土曜日

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

ロジックを直接コーディングするのではなく、あるパターンをもったロジックを生成する高位ロジックによってプログラミングを行う方法、またその高位ロジックを定義する方法のこと。........wikipedia

13年7月27日土曜日

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

いみが まったくわからない

いやん♡

13年7月27日土曜日

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

プログラムを生成するプログラム、ってことでいいと思うぽよ。

ようは

13年7月27日土曜日

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

例えばYACCexpression : 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日土曜日

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

YACC

.y YACC .c

13年7月27日土曜日

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

YACC

.y YACC .c

ドメイン言語(DSL)

ホスト言語

13年7月27日土曜日

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

boost.spiritexpr = ( 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日土曜日

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

boost.spirit

.cpp

13年7月27日土曜日

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

boost.spirit

.cppドメイン言語 ホスト言語

13年7月27日土曜日

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

boost.spirit

.cppドメイン言語 ホスト言語

EDSL(埋め込みドメイン言語)

13年7月27日土曜日

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

boost.spirit

.cppドメイン言語 ホスト言語

EDSL(埋め込みドメイン言語)

YACC相当のものは?

13年7月27日土曜日

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

boost.spirit

.cppドメイン言語 ホスト言語

EDSL(埋め込みドメイン言語)

YACC相当のものは?

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

13年7月27日土曜日

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

なぜC++でメタプロ?

別の構文規則を学ぶ必要がない

他のメタプロとの相互運用

余分な構築ステップ不要

品質、再利用、可搬性

13年7月27日土曜日

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

とはいえ

boost.spiritのような究極のメタプログラミングの話は割愛します。

このあとの章では、C++メタプロを支える基本的な部分だけお話します。 (ちゃんと話せる自信がないというのはナイショぽよ

13年7月27日土曜日

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

メタプログラムとは何か?

テンプレートの基礎テンプレート特殊化

再帰テンプレート

メタ関数

型シーケンス

さいごに

13年7月27日土曜日

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

普通のジェネリック// C#List<string> list = new List<string>();list.add("hoge"); list.add("page");

// JavaList<String> list = new ArrayList<String>();list.add("hoge"); list.add("page");

//C++list<string> list;list.insert("hoge"); list.insert("page");

13年7月27日土曜日

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

非型テンプレート

//C++template<int N>struct pow { static const int value = N*N;};

int n = pow<3>::value; // n = 3*3;

13年7月27日土曜日

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

型の操作 ポインタを追加する

//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日土曜日

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

C++テンプレート

コンパイル時に計算してしまう(実行時コスト0)。

非型テンプレート

型操作

.....などなど

13年7月27日土曜日

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

メタプログラムとは何か?

テンプレートの基礎

テンプレート特殊化再帰テンプレート

メタ関数

型シーケンス

さいごに

13年7月27日土曜日

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

add_pointerの例ん??

// int* p = &n;add_pointer<int>::type p1 = &n;

// これはエラー:int** p2 = &n;add_pointer<int*>::type p2 = &n;

13年7月27日土曜日

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

そこで特殊化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日土曜日

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

テンプレート特殊化

テンプレート特殊化により、コンパイル時に条件分岐を行うことができる。

13年7月27日土曜日

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

コンパイル時 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日土曜日

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

コンパイル時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日土曜日

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

C++テンプレート

コンパイル時に計算してしまう(実行時コスト0)。

非型テンプレート

型操作

特殊化による条件分岐

13年7月27日土曜日

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

メタプログラムとは何か?

テンプレートの基礎

テンプレート特殊化

再帰テンプレートメタ関数

型シーケンス

さいごに

13年7月27日土曜日

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

普通に再帰で階乗計算

int factorial(int N) { return N==0 ? 1 : N*factorial(N-1);}

int n = factorial(3); // 6

13年7月27日土曜日

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

再帰テンプレートで// 階乗を求める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日土曜日

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

再帰テンプレート

再帰テンプレートにより、コンパイル時に繰り返し処理を行うことができる。

13年7月27日土曜日

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

余談

C++テンプレートはチューリング完全である(制限:再帰に限界あり)C++ Templates are Turing Complete

http://ubietylab.net/ubigraph/content/Papers/pdf/CppTuring.pdf

13年7月27日土曜日

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

C++テンプレートコンパイル時に計算してしまう(実行時コスト0)。

非型テンプレート

型操作

特殊化による条件分岐

再帰テンプレートによる繰り返し

13年7月27日土曜日

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

このへんからちょっとだけ応用な感じです。

ちょっとだけよ♡

13年7月27日土曜日

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

メタプログラムとは何か?

テンプレートの基礎

テンプレート特殊化

再帰テンプレート

メタ関数型シーケンス

さいごに

13年7月27日土曜日

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

メタ関数とは

add_pointer<int>::type pi;

関数名

int v = factorial_t<3>::value;

パラメータ 戻り値(型)

関数名 パラメータ 戻り値(値)

13年7月27日土曜日

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

高階関数を考えてみようまずは普通のテンプレート関数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日土曜日

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

高階メタ関数

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日土曜日

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

メタプログラムとは何か?

テンプレートの基礎

テンプレート特殊化

再帰テンプレート

メタ関数

型シーケンスさいごに

13年7月27日土曜日

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

こんなことしたいそれぞれの型のインスタンスを用意してメソッドを呼び出したい。

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日土曜日

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

JavaやC#、ObjCあたりのアプローチリフレクションを使う。

Classクラスのようなメタクラスの配列を使って動的生成する、とかね。

C++のリフレクションは貧弱。

どうしよう。

13年7月27日土曜日

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

C++のアプローチメタプログラミングで型のリスト(型シーケンス)を用意し、各型にアクセスする仕掛けを考えてみる。

TypeList<A,B,C,D>::type;

13年7月27日土曜日

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

C++のアプローチメタプログラミングで型のリスト(型シーケンス)を用意し、各型にアクセスする仕掛けを考えてみる。

TypeList<A,B,C,D>::type;

このへんをどうするか??

13年7月27日土曜日

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

型シーケンス

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日土曜日

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

型シーケンス

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日土曜日

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

むずくないよ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日土曜日

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

あとは繰り返す処理// 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日土曜日

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

ターミネータ忘れてた!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日土曜日

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

使ってみよう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日土曜日

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

リフレクションが無くても

テンプレートでいろいろ出来ちゃう。

しかも多くをコンパイル時に静的に。

boost.mpl には型のためのコンテナ、イテレータ、アルゴリズムがある。遅延評価、ラムダなども。正直、あたまおかしい(笑)

13年7月27日土曜日

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

メタプログラムとは何か?

テンプレートの基礎

テンプレート特殊化

再帰テンプレート

メタ関数

型シーケンス

さいごに13年7月27日土曜日

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

新たなパラダイムに出会えたね!

構造化

データ指向

オブジェクト指向

ジェネリック

関数型

・・・

メタプログラミング13年7月27日土曜日

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

余談GoFデザインパターンはオブジェクト指向だけか?

例えば Abstract FactoryパターンやVisitor パターンは、メタプロと相性が良い。

継承でなくポリシとか。

メタプロと関数型?

どちらも状態を持たない

13年7月27日土曜日

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

まとめ

C++テンプレート機能により、コンパイル時の処理を書くことが出来る。

ライブラリの実装では多用される。

でも、正直読みにくいし難解。C++11ではconstexprにより多少ましになっている。

13年7月27日土曜日

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

おつかれさま!

もうおわり?♡

ふう...

13年7月27日土曜日