More Related Content
Similar to C++ Template Meta Programming の紹介@社内勉強会
Similar to C++ Template Meta Programming の紹介@社内勉強会 (20)
More from Akihiko Matuura
More from Akihiko Matuura (6)
C++ Template Meta Programming の紹介@社内勉強会
- 9. 例えば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日土曜日
- 12. 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日土曜日
- 21. 普通のジェネリック
// 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日土曜日
- 26. add_pointerの例
ん??
// int* p = &n;
add_pointer<int>::type p1 = &n;
// これはエラー:int** p2 = &n;
add_pointer<int*>::type p2 = &n;
13年7月27日土曜日
- 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日土曜日
- 29. コンパイル時 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日土曜日
- 30. コンパイル時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日土曜日
- 34. 再帰テンプレートで
// 階乗を求める
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日土曜日
- 42. 高階メタ関数
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日土曜日
- 44. こんなことしたい
それぞれの型のインスタンスを用意してメソ
ッドを呼び出したい。
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日土曜日
- 48. 型シーケンス
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日土曜日
- 49. 型シーケンス
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日土曜日
- 50. むずくないよ
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日土曜日
- 51. あとは繰り返す処理
// 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日土曜日
- 52. ターミネータ忘れてた!
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日土曜日
- 53. 使ってみよう
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日土曜日