Level 3:関数 3.7 関数テンプレート |
※資料は自著より引用
■3.7 関数テンプレート
●テンプレートテクニック
次のソースコードで定義されている引数付きマクロ mySortTemplate( T ) は,T型要素の配列を
整列できる関数 mySort( ) の定義を展開するように作成されている(9〜28行目)。
この引数付きマクロ mySortTemplate( T ) は,
あらかじめ特定の要素型の配列を第1引数を受け
取る関数 mySort( ) のオーバロードバージョンの定義をマクロ展開しておくことである。
・
30行目では, mySortTemplate( int ) として,第1引数に int型配列を受け取る
関数 void mySort( int a[ ], size_t element_num, ::sortFlag flag ); の定義をマクロ展開している。
・
31行目では, mySortTemplate( double ) として,第1引数に double型配列を受け取る
関数 void mySort( double a[ ], size_t element_num, ::sortFlag flag ); の定義をマクロ展開している。
そうして,その関数の必要なオーバロードバージョンの定義をマクロ展開しておき,それを呼び出して
いる(45,46,53,54行目)。
・マクロ定義による関数定義の一元化 sort4.cpp
●マクロ展開によるテンプレートテクニックの利点と欠点
●関数テンプレート
・関数テンプレートを利用した例 sort5.cpp
●関数テンプレートの仕組み
ソースコードはこちら。 クリックして画像が切り替えられます。
授業内練習問題:※リファレンスとテンプレートを個別に使った課題はこちら
上図で例に挙げた2つの引数の値を交換するテンプレート関数 mySwap( ) を,ポインタで引数を受け取る形ではなく,
リファレンスで引数を受け取る様に改良せよ。mySwap1.cpp
#include <iostream> using namespace std; template< class T > void mySwap( /* ここを完成させよ */ ) { T temp = a; a = b; b = temp; } int main( void ) { int x = 10, y = 20; mySwap( x, y ); cout << "x is " << x << endl << "y is " << y << endl; double dx = 100.0, dy = 200.0; mySwap( dx, dy ); cout << "dx is " << dx << endl << "dy is " << dy << endl; char c; cin >> c; // 1文字タイプしてエンターキー return 0; }
●関数テンプレートの注意点
注意点1:複数の異なるテンプレート仮引数を使用できる。
以下は,二つの実引数のデータサイズを比較して第1実引数のサイズの方が大きいときは1を返し,
そうでない場合は0を返す関数 greater( ) の定義例。テンプレート関数の定義部分で,
< class T1, class T2 > というように,2つのテンプレート仮引数T1とT2が宣言されている。
#include <iostream> #include <cstdlib> using namespace std; // 第1実引数のバイトサイズ > 第2実引数のバイトサイズ の場合 1 を返し, // そうでないなら 0 を返す関数 greater( )。 template< class T1, class T2 > bool greater( const T1 & a, const T2 & b ) { return sizeof( a ) > sizeof( b ); } int main( void ) { int i; short s; double d; cout << greater( i, d ) << endl; // 0 と表示。bool greater( const int & a, const double & b ); の定義が自動生成されて使われる。 cout << greater( i, s ) << endl; // 1 と表示。bool greater( const int & a, const short & b ); の定義が自動生成されて使われる。 char c; cin >> c; // 1文字タイプしてエンターキー return 0; }注意点2:テンプレート 仮引数は返値型にも使用できる(ただし,関数仮引数にテンプレート仮引数を組み込んでおくこと)。
#include <iostream> using namespace std; template< class T > T maxElement( const T a[ ], size_t num ) { T max = a[ 0 ]; for( size_t i = 1; i < num; i++ ) { if( a[ i ] > max ) max = a[ i ]; } return max; } int main( void ) { int ia[ ] = { -10, 2, 4, 51, -100, 17 }; double da[ ] = { -123.0, 2.0, 4.0, 27.0, 7.0 }; cout << maxElement( ia, 6 ) << endl; // 51 と表示。 int maxElement( int a[ ], size_t num ); の定義が自動生成されて使われる。 cout << maxElement( da, 5 ) << endl; // 27 と表示。 double maxElement( double a[ ], size_t num ); の定義が自動生成されて使われる。 char c; cin >> c; // 1文字タイプしてエンターキー return 0; }