クラステンプレートの例

template<typename T1, typename T2>
  class pair
  {
  public:
      T1 first;
      T2 second;
  };

int main()
{
  pair<int,char> x;
  x.first  = 100;
  x.second = 'A';

  pair< float, pair<int,int> > y;
  x.first = 10.5;
  x.second.first = 100;
  x.second.first = 200;
}

関数テンプレートの例

template<typename T>
  T max( T x, T y )
  {
    if( x < y ) return y;
    else        return x;
  }

int main()
{
  int   n = max( 100, 200 ); // n=200
  float f = max( 1.2, 3.4 ); // f=3.4

  // コンパイルエラーになる例
  max( 100, 3.4 ); // エラー:型Tが推論できない

  // コンパイルエラーになる例
  class MyClass {};
  MyClass x, y;
  max( x, y ); // エラー:MyClass型は<演算子で比較できない

  // コンパイルエラーにならない例
  class MyClass2 {
    public: bool operator<(MyClass2 rhs) { return true; }
  };
  MyClass z, w;
  max( z, w );
}

テンプレート色々

普通の

template<typename T>
  class Hoge { ... };
Hoge<int> x;

多引数

template<typename T1, typename T2, typename T3>
  class Hoge { ... };
Hoge<int,string,float> x;

デフォルト引数

template<typename T1, typename T2 = int>
  class Hoge { ... };
Hoge<int> x;     // Hoge<int,int>

デフォルト引数

template<typename T1, typename T2 = vector<T1> >
  class Hoge { ... };
Hoge<int> x;     // Hoge<int,vector<int>>

型以外のパラメータ

template<int N>
  class Hoge { ... };
Hoge<1024> x;

型以外のパラメータ

template<template<typename> class Tx>
  class Hoge { Tx<int> x; ... };

template<typename T>
  class Fuga { ... };

Hoge<Fuga> x;

テンプレートの特殊化

A:一般の場合

template<typename T>
  class Vector
  {
     T*  data_buffer;
     int size;
  public:
     Vector( int initial_size )
     {
        data_buffer = new T[ initial_size ];
        size        = initial_size;
     }
     T get_at(int i)
     {
        if( 0<i || size<=i ) error();
        return data_buffer[i];
     }
  };

B:boolの場合の特殊化

template<>
  class Vector<bool>
  {
     byte* data_buffer;
     int   size;
  public:
     Vector( int initial_size )
     {
        data_buffer = new byte[ initial_size/8+1 ];
        size        = initial_size;
     }
     bool get_at(int i)
     {
        if( 0<i || size<=i ) error();
        return (data_buffer[i/8] >> i%8) == 1;
     }
  };

C:使用例

int main()
{
  Vector<int>  v1;  // Aの方が使われる
  Vector<bool> v2;  // Bの方が使われる
}

テンプレートの部分特殊化

A:一般の場合

template<typename T1, typename T2>
  class MyTemplate {};

B:ポインタの場合の部分特殊化

template<typename T1, typename T2>
  class MyTemplate<T1*,T2*> {};

C:片方がintの場合の部分特殊化

template<typename T1>
  class MyTemplate<T1,int> {};

D:片方がfloat,片方がpairの場合の部分特殊化

template<typename T>
  class MyTemplate< float,pair<T,T> > {};

E:使用例

MyTemplate<char,int> x; // Bが使われる
MyTemplate<float,pair<string,string> > y; // Dが使われる
MyTemplate<float,pair<string,int> > y; // Aが使われる

STL

アルゴリズム

template<typename Iterator, typename Function>
  void for_each( Iterator it, Iterator end, Function f )
  {
     while( it != end )
     {
       f( *it );
       ++it;
     }
  }

MetaProgramming

フィボナッチ

template<int N>
  class fib {
    static const int val =
        fib<N-1>::val
      + fib<N-2>::val
  };
template<>
  class fib<0> {
    static const int val = 1
  };
template<>
  class fib<1> {
    static const int val = 1
  };

Expression Template

普通の行列演算ライブラリ

matrix operator+( matrix x, matrix y ) { ... }
matrix operator*( matrix x, matrix y ) { ... }

Expression Templateを使った行列演算ライブラリ

template<typename L,typename R>
  add<L,R> operator+( L x, R y ) { ... }
template<typename L,typename R>
  mul<L,R> operator*( L x, R y ) { ... }

Expression Templateを使った行列演算ライブラリ:実装概略

template<typename L,typename R>
  class add
  {
     L& l;
     R& r;
     float operator[](int i,int j) { return l[i][j]+r[i][j]; }
  };

template<typename L,typename R>
  class mul
  {
     L& l;
     R& r;
     float operator[](int i,int j) {
       float acc=0;
       for(int k=0; k<N; ++k)
         acc += l[i][k]*r[k][j];
       return acc;
     }
  };

class matrix
{
  template<typename Expr>
    void operator=( Expr e )
    {
       for(int i=0; i<N; ++i)
         for(int j=0; j<N; ++j)
          (*this)[i][j] = e[i][j];
    }
};