技術的なやつ

技術的なやつ

1.1 テンプレート ~汎用探索パッケージ制作~

ようやく余裕が出てきたので、この辺で作業を進めておく。
汎用探索パッケージを制作するに当たって、まずはC++のテンプレートについて基本を押さえる。

テンプレートはC++に後年標準化された機能(?)で、あらゆる型に対応したオーバーロード関数・クラスをコンパイル時に自動生成する。
つまり、テンプレートが実装される前は、int型とfloat型に対応したswapは以下のように定義しなければならなかった。*1

void swap(int &a, int &b){
	int c = a;
	a = b;
	b = c;
}

void swap(float &a, float &b){
	float c = a;
	a = b;
	b = c;
}

このように、実質やっていることは同じだが、引数の型に応じていちいち関数を書かなければならなかったのである。
その問題を解決するのがテンプレートで、上のようなswapを表現するには、以下のように書けばよい。

template <class d_type> void swap(d_type &a, d_type &b){
	d_type c = a;
	a = b;
	b = c;
}

上のコードで言うと、d_typeが様々な変数の型の肩代わりをしてくれて(ギャグでは無い)、コンパイル時に必要な型のオーバーロード関数を自動生成してくれる。便利である。

テンプレートを使用するには、以下のキーワードが必要だ。

template <class hoge>

この直後に、テンプレートを使用する関数(あるいはクラス、構造体)を宣言する。classはtypenameと置換可能である。typenameを使うと、テンプレート内で新たなテンプレートを宣言することが出来るらしい(独習C++には詳しく書いていなかった)。
被テンプレート雛形の宣言はtemplate の後に改行を挟んでいても良いが、テンプレート宣言の直後でないといけない。すなわち、以下のコードはエラーが発生する。

template <class hoge>
int i; //error!
void foo(hoge x){
	// ...
}

ここで、独習C++の練習問題11.1.3を解こう。

テンプレート関数の好例として、find()という関数があります。この関数は、配列内であるオブジェクトを検索します。オブジェクトが見つかった場合はそのオブジェクトのインデックスを返し、オブジェクトが見つからなかった場合は-1を返します。

template <class d_type>
int find(d_type object, d_type *list, int size){
	for(int i=0; i<size; i++){
		if(object == list[i])	return i;
	}
	return -1;
}

*1:私は参照渡しが大嫌いなのだが、ここはC++っぽく参照渡しで書いておく