templateの概念からTMPの応用まで

# [alpha_kai_NET](https://twitter.com/alpha_kai_NET)氏との会話
「あ、テンプレート is 何ってのが」
「あー、テンプレートか。オーバーロードってあるじゃん？」
「例えば

```cpp
void abc(int arg)
```

と

```cpp
void abc(char arg)
```

を別個に定義できるやつですよね」
「そうそう。
オーバーロードで例えばこういうのがあるとする

```cpp
int add ( int x , int y )
{
    return x + y ;
}
double add ( double x , double y )
{
    return x + y ;
}
```

`add`という名前で`int`版と`double`版がある」
「ほうほう」
「で、これを`float`にも対応させたい
こうなる

```cpp
int add ( int x , int y )
{
    return x + y ;
}
double add ( double x , double y )
{
    return x + y ;
}
float add ( float x , float y )
{
    return x + y ;
}
```

」
「ふむふむ」
今度は`long`にも
こうなる

```cpp
int add ( int x , int y )
{
    return x + y ;
}
double add ( double x , double y )
{
    return x + y ;
}
float add ( float x , float y )
{
    return x + y ;
}
long add ( long x , long y )
{
    return x + y ;
}
```

」
「もしかして:コードが長くなるのを解消する機能」
「そそ
これが例えば誰かの作った`UserDefineInt`とかにも対応させたい、とかなったらキリがない
というわけで

```cpp
template < typename T >
T add ( T x , T y )
{
    return x + y ;
}
```

これでおｋ」
「あー、型を推論してくれるのかな？」
「そうそう
`add(1,2)`ッて書いたら`add<int>`が推論されるし
`add(1.0,2.5)`ッて書いたら`add<double>`が推論される
これらはコンパイラが勝手に導出してくれる」
「かなり便利そう(C言語マン」
「yes
めちょべんり
で、これはクラスにも使える」
「fmfm」
「

```cpp
class vector_int { /* ... */ } ;
class vector_long { /* ... */ } ;
class vector_double { /* ... */ } ;
```

とか延々あったら面倒くさいので

```cpp
template < typename T >
class vector { /* ... */ } ;
```

こう書いておけば」
「(C++のクラスよく知らない)」
「あー
とりあえず`struct`の強化版って思ってたら間違いない」
「まー、感覚的には」
「さて
となるとこっちのほうがいいかな

```cpp
struct vector_int { /* ... */ } ;
struct vector_long { /* ... */ } ;
struct vector_double { /* ... */ } ;
```

これをこう書き換えれば

```cpp
template < typename T >
struct vector { /* ... */ } ;
```

`vector < int >`や`vector < double >`とか`vector < UserDefineType >`とかできる
いちいちそれぞれの型ごとに作ってやらなくても良くなる」
「! 最強じゃないか！(小並感)」
「いぇあ
ちなみに`template`、便利な機能があって
「ほう」
「たとえばさっきの`vector`で`int`の時だけ最適化した実装にしたいとする

```cpp
template < typename T >
struct vector { /* ... */ } ;
template < >
struct vector < int > { /* ... */ } ;
```

こうすれば`int`バージョンだけ作れる
`hoge < T >`の時だけ最適化した実装を作りたい

```cpp
template < typename T >
struct vector { /* ... */ } ;
template < typename T >
struct vector < hoge < T > > { /* ... */ } ;
```

こうすればおｋ」
「基本は`template`で指定した型だけ強化、なるほど」
「そうそう、基本的に共通の実装を提供するんだけど、特定のパターンの型だけ特殊化できる
じゃあ、ここからすこしだけTMPの話入るけど続けるよ？
C++では`struct`の中で`typedef`ができるってのがある
要するにこうできる

```cpp
struct some_struct
{
    typedef hoge_type hogehoge_type ;
} ;
```

使うときは`some_struct::hogehoge_type`とかやる
構造体やクラスのメンバとして`typedef`を定義できる、ということ」
「えーと、まず、Cの`struct`が曖昧ってのが(」
「あー、今はとりあえずCの構造体は変数をまとめるものだと思ってたらいいと思うし実際そう
で、C++だとそれに加えて関数や`typedef`もまとめれる、ということ」
「なるほどー、関数を持てる構造体的な？」
「そうそう。`typedef`も持てる
で、`typedef`の場合は`some_struct::hogehoge_type`みたいに使える
`hoge_type`が`int`なら`int`になる
おｋ？」
「`typedef`？」
「

```cpp
typedef int my_type ;
```

で、`my_type`が`int`の別名として使える」
「ああ、そういうことねなるほど理解」
「\*nixの`alias`みたいなの(型バージョン)
うん
で

```cpp
struct some_struct
{
    typedef hoge_type hogehoge_type ;
} ;
```

だと、`some_struct::hogehoge_type`が`hoge_type`の別名になる
`hoge_type`が`int`なら`int`だし、`double`なら`double`
ここまではおｋ？」
「おけ」
「うん
で、これはもちろん`template`な`struct`や`class`に対しても行える

```cpp
template < typename T >
struct some_struct
{
    typedef hoge_type hogehoge_type ;
} ;
```

みたいな」
「ほう」
「そして、こんなこともできる

```cpp
template < typename T >
struct some_struct
{
    typedef T hogehoge_type ;
} ;
```

」
「やっぱりできるんだ！(予想してた」
「うん
で、
これと`template`の特殊化を組み合わせると、例えば「`T`が`int`なら○○、`T`が`double`なら△△、`hoge < T >`なら□□
とかもできる」
「すげー(感嘆」
「うん
さて、これあるものに似ているんだけど、わかる？」
「うーん、なんか既視感あるんだけど」
「関数」
「あ！、なるほど」
「`T`を引数として考えて、メンバ`typedef`を戻り値として考えると、まんま関数なわけ
ただし引数と戻り値はそれぞれ型
こうして考えると、構造体は関数に似たものとして考えることができる
という発想で行うプログラミングを、Template Meta Programmin、略してTMP」
「だから、型でプログラミング(?)してるなって感じたのかな」
「おー
その感覚ｲｲｿﾞｰ」
「C++たのしい！」
「これがそれなりに複雑になると例えばこんなこともできる
http://qiita.com/minamiyama1994/items/b8f1185ed93b6835c239
Cなんかの`switch`文の高級バージョン(Haskellなんかにあるパターンマッチ文)を`template`で実現しちゃおうっていうやつ
TMPでゴニョゴニョすればこういうこともできる」
「やばい(やばい)」
「このへんかな、あ、そうそう、大事なこと忘れてた
こういうTMPとかってなんのために行うか、何だけど」
「fm」
「

> たとえばさっきの`vector`で`int`の時だけ最適化した実装にしたいとする
> 
> ```cpp
> template < typename T >
> struct vector { /* ... */ } ;
> template < >
> struct vector < int > { /* ... */ } ;
> ```
> 
> こうすれば`int`バージョンだけ作れる
> `hoge < T >`の時だけ最適化した実装を作りたい
> 
> ```cpp
> template < typename T >
> struct vector { /* ... */ } ;
> template < typename T >
> struct vector < hoge < T > > { /* ... */ } ;
> ```
> 
> こうすればおｋ

こういうのあったじゃん？」
「おう、ありましたな」
「ここで`hoge < T >`のときに最適化というのがあるのだけれど
ここがもっと複雑で「`T`が○○で△△な条件を満たしているかもしくは～」
みたいな複雑な条件の場合に最適化、というのを考えると、TMPが使える」
「ほう」
「あと、Expression Templateという技法がある」
「ほう」
「C++には演算子オーバーロードっていうのがあって、ユーザ定義型に対して演算子(`+`、`-`、`*`、`/`など)を普通の関数みたいにオーバーロードできるって機能なのだけれど」
「ほうほう」
「

```cpp
template < typename T1 , typename T2 >
HogeType < T1 , T2 > operator + ( T1 t1 , T2 t2 ) ;
```

こういうのを考えてみると、`T1`型のオブジェクト`t1`と`T2`型のオブジェクト`t2`で`t1 + t2`ってやると型として、`HogeType < T1 , T2 >`が手に入る
で、この`HogeType < T1 , T2 >`を元に最適化をやったり、特殊な処理を行ったり、ってのができる
これなんか変態的な例かな
http://www.kmonos.net/alang/boost/classes/lambda.html
」
「む」
「`find_if`や`for_each`の第3引数には普通関数を入れるんだけど、関数を即席の式で作っちゃえ、というライブラリ」
「演算子オーバーロードって演算子の拡張?(混乱」
「そうそう
ユーザ定義型に対して演算子を再定義してやる
で、ここでの`_1`とかはライブラリ側が定義したユーザ定義型を持ってるから、演算子オーバーロードが使える」
「なるほど」
「で、それとExpression TemplateとTMPを使って、即席で関数を作ってる
`_1%5==0 && _1>30`
なら「第一引数が`5`の倍数かつ`30`より大きい場合に真を返す」関数を即席で作ってる」
「lambda的な？」
「そうそうまさしくlambda式
と言うヤバいことも出来るよ、というお話でした」
「なるほどな、C++やばいすごい」
「やったぜ」