クラステンプレートの例
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];
}
};