• 検索結果がありません。

型パラメータ付きの関数定義

ドキュメント内 新潟大学学術リポジトリ (ページ 183-187)

14

15 for (int i=0; i<a.getSize(); i++) { 16 a[i] = i+10;

17 b[i] = i*i;

18 }

19 showContentsOf("a", a);

20 showContentsOf("b", b);

21

22 a = b;

23 cout << "a = b;" << endl;

24 cout << "==> ";

25 showContentsOf("a", a);

26 } 27

28 void showContentsOf(string arrayName, SafeArray<int> a) 29 {

30 cout << arrayName << ".size=" << a.getSize() << ", "

31 << arrayName << "=(";

32 for (SafeArray<int>::iterator p=a.begin(); p!=a.end(); ++p) 33 cout << right << setw(4) << *p;

34 cout << ")" << endl;

35 }

[motoki@x205a]$ g++ useSafeArrayInt.cpp [motoki@x205a]$ ./a.out

a.size=10, a=( 10 11 12 13 14 15 16 17 18 19) b.size=10, b=( 0 1 4 9 16 25 36 49 64 81) a = b;

==> a.size=10, a=( 0 1 4 9 16 25 36 49 64 81) [motoki@x205a]$

ここで、

3 利用例のプログラム32∼33行目 では、全ての配列要素を出力する繰り返し処理が データ集合 {a[0], a[1], ..., a[a.size-1]} を保持する方法に依存しない形で記 述されている。この32∼33行目に現れる変数 p の様に、処理する要素を次々に指 すiterator型の変数を反復子(iterator,イテレータ) と呼ぶ。

6.2 型パラメータ付きの関数定義

{Pohl(1999)7.2節} 通常の関数内に現れるデータ型の部分をパラメータ化することもできる。型パラメータ 付きの関数をテンプレート関数もしくは関数テンプレートと呼ぶ。

例 6.3 (配列全体をコピーする型パラメータ付き関数) 指定された型パラメータTYPE1,

TYPE2に対して「TYPE2型配列をTYPE1型配列に要素単位でコピーするテンプレート関数

178 6. パラメータ付きのクラス定義、総称的プログラミング、STL

copy()」、および指定された型パラメータTYPEに対して「TYPE型配列の要素列を出力す

るテンプレート関数print()」を定義し使用した例を次に示す。

[motoki@x205a]$ cat -n useTemplateCopy.cpp

1 // 型パラメータ付きの関数 copy() の定義・利用例 2

3 #include <iostream>

4 #include <iomanip>

5 #include <string>

6 using namespace std;

7

8 template<typename TYPE1, typename TYPE2>

9 void copy(TYPE1 x[], TYPE2 y[], int size);

10

11 template<typename TYPE>

12 void print(string arrayName, TYPE x[], int size);

13

14 int main() 15 {

16 double a[5] = {1.1, 2.2, 3.3, 4.4, 5.5}, b[5];

17 int m[5];

18

19 print("a", a, 5);

20 ::copy(b, a, 5);

21 print("b", b, 5);

22

23 ::copy(m, a, 5);

24 print("m", m, 5);

25 } 26

27 template<typename TYPE1, typename TYPE2>

28 void copy(TYPE1 x[], TYPE2 y[], int size) 29 {

30 for (int i=0; i<size; ++i) 31 x[i] = y[i];

32 } 33

34 template<typename TYPE>

35 void print(string arrayName, TYPE x[], int size) 36 {

37 cout << arrayName << "[" << size << "] = {" << scientific << fixed;

38 for (int i=0; i<size-1; ++i) 39 cout << x[i] << ", ";

40 cout << x[size-1] << "}" << endl;

6.2. 型パラメータ付きの関数定義 179

41 }

[motoki@x205a]$ g++ useTemplateCopy.cpp [motoki@x205a]$ ./a.out

a[5] = {1.100000, 2.200000, 3.300000, 4.400000, 5.500000}

b[5] = {1.100000, 2.200000, 3.300000, 4.400000, 5.500000}

m[5] = {1, 2, 3, 4, 5}

[motoki@x205a]$

ここで、

• プログラム20行目,23行目 でスコープ解決演算子:: を用いているのは、標準ライブ ラリstd内で定義されたcopy()関数を適用候補から除外するためである。

例 6.4 (2つの変数の中身を交換する型パラメータ付き関数) 例2.5で定義した関数void swap(int&, int&) の引数の型の部分をパラメータ化し、指定された型パラメータTYPE に対して「TYPE型の2つの変数の中身を交換する(テンプレート)関数swap()」を定義し 使用した例を次に示す。

[motoki@x205a]$ cat -n useTemplateSwap.cpp

1 // 型パラメータ付きの関数 swap() の定義・利用例 2

3 #include <iostream>

4 #include <cstring>

5 using namespace std;

6

7 template<typename TYPE>

8 void swap(TYPE& x, TYPE& y);

9

10 void swap(char* x, char* y);

11

12 int main() 13 {

14 int i=1, j=22;

15 double a=33.3, b=444.4;

16 char str1[]="abcd", str2[]="1234";

17

18 ::swap(i, j);

19 cout << "i=" << i << ", j=" << j << endl;

20

21 ::swap(a, b);

22 cout << "a=" << a << ", b=" << b << endl;

23

24 ::swap(str1, str2);

25 cout << "str1=" << str1 << ", str2=" << str2 << endl;

26 }

180 6. パラメータ付きのクラス定義、総称的プログラミング、STL

27

28 template<typename TYPE>

29 void swap(TYPE& x, TYPE& y) 30 {

31 TYPE temp;

32

33 temp = x;

34 x = y;

35 y = temp;

36 } 37

38 void swap(char* x, char* y) 39 {

40 int maxLength = max(strlen(x), strlen(y));

41 char* temp = new char[maxLength+1];

42

43 strcpy(temp, x);

44 strcpy(x, y);

45 strcpy(y, temp);

46 delete[] temp;

47 }

[motoki@x205a]$ g++ useTemplateSwap.cpp [motoki@x205a]$ ./a.out

i=22, j=1

a=444.4, b=33.3 str1=1234, str2=abcd [motoki@x205a]$

ここで、

• プログラム18行目,21行目,24行目 でスコープ解決演算子 :: を用いているのは、標 準ライブラリstd内で定義されたswap()関数を適用候補から除外するためである。

• プログラム40行目 に現れるmax()は、標準ライブラリstd内で定義されたmax()関 数を表す。

• プログラム24行目 の関数呼び出し ::swap(str1, str2); に対しては、28∼36行目 で定義されたテンプレート関数も、38∼47行目で定義された非テンプレート関数も適 用可能である。こういう場合は、非テンプレート関数の方が優先的に適用される。一 般に、適用可能な関数が複数あった時は、次の順に優先的に選ばれる。

1 自明の型変換を行うことによりシグネチャが合致する非テンプレート関数 2 適切に型パラメータを設定することによりシグネチャが合致するテンプレート

関数

3 非テンプレート関数上での通常の選択手順による関数(−→2.11節を参照)

ドキュメント内 新潟大学学術リポジトリ (ページ 183-187)