研究生のためのc++ no.4

36
C++ For Researchers 研究生のためのC++ 企画・立案 難波知宏

Upload: tomohiro-namba

Post on 21-Mar-2017

63 views

Category:

Software


0 download

TRANSCRIPT

Page 1: 研究生のためのC++ no.4

C++ For Researchers 研究生のためのC++

企画・立案 難波知宏

Page 2: 研究生のためのC++ no.4

テンプレート

第四回

2

Page 3: 研究生のためのC++ no.4

関数テンプレート

第一節

3

Page 4: 研究生のためのC++ no.4

関数テンプレートとは

4

Sample 4-1

Page 5: 研究生のためのC++ no.4

5

そうだ、max関数を作ろう

Page 6: 研究生のためのC++ no.4

sample 4-1-1

int max(int x, int y) {

return (x > y) ? x : y;

}

6

関数テンプレートとは

Sample 4-1

従来のプログラム

double版も欲しくなった

e ? a : b e が true のとき a false のとき b を返す

Page 7: 研究生のためのC++ no.4

sample 4-1-1

int max(int x, int y) {

return (x > y) ? x : y;

}

double max(double x, double y) {

return (x > y) ? x : y;

}

7

関数テンプレートとは

Sample 4-1

従来のプログラム

データ型が違うだけで

同じ処理なのに、

別々に記述

何とかして一つに

まとめられないか?

Page 8: 研究生のためのC++ no.4

8

テンプレートで

できますよ

Page 9: 研究生のためのC++ no.4

sample 4-1-2

template <typename Type>

Type max(Type x, Type y)

{

return (x > y) ? x : y;

}

9

関数テンプレートとは

Sample 4-1

テンプレートを使って一つにまとめる

データ型に依存

しない関数

template <…>

を関数の前につけると、

関数テンプレートになる.

Page 10: 研究生のためのC++ no.4

テンプレート引数の明示指定

Sample 4-2

10

Page 11: 研究生のためのC++ no.4

sample 4-2-1

template <typename Type>

Type max(Type x, Type y)

{

return (x > y) ? x : y;

}

int main()

{

double c = max(7, 3.0); // Compile error!

}

11

テンプレート引数の明示指定

Sample 4-2

次のプログラムはコンパイルエラーになります。

テンプレート引数Typeをintとdoubleのどちらに

したらいいかわからない!

コンパイラ

Page 12: 研究生のためのC++ no.4

sample 4-2-1

template <typename Type>

Type max(Type x, Type y)

{

return (x > y) ? x : y;

}

int main()

{

double c = max<double>(7, 3.0); // OK.

}

12

テンプレート引数の明示指定

Sample 4-2

<…>でテンプレート引数の型を指定すればよい。

実は、テンプレート引数

が省略された場合、

コンパイラが自動で

推論しているんだよね

コンパイラ

Page 13: 研究生のためのC++ no.4

関数テンプレートの特殊化

13

Sample 4-3

Page 14: 研究生のためのC++ no.4

14

string型でもmax関数が動くようにしたい

Page 15: 研究生のためのC++ no.4

15

そんでもって

string型の場合は、長さが大きい方を返したい

Page 16: 研究生のためのC++ no.4

sample 4-3-1

#include <string>

template <typename Type>

Type max(Type x, Type y) {

return (x > y) ? x : y;

}

int main()

{

double c = max<double>(7, 3.0); // OK.

char* d = max<char*>("hoge", "hogehoge");// NG (Unexpected result).

}

16

関数テンプレートの特殊化

Sample 4-3

従来のプログラム

期待通りに

ならない

Page 17: 研究生のためのC++ no.4

sample 4-3-2

#include <string>

template <typename Type>

Type max(Type x, Type y) {

return (x > y) ? x : y;

}

template <>

char* max(char* x, char* y) {

return (strlen(x) > strlen(y)) ? x : y;

}

int main() {

double c = max<double>(7, 3.0); // OK.

char* d = max<char*>("hoge", "hogehoge"); // OK.

}

17

関数テンプレートの特殊化

Sample 4-3

特殊化をすれば、文字列専用の処理ができる

テンプレート引数がchar*

の場合は、例外的にこの

関数が呼ばれる

Page 18: 研究生のためのC++ no.4

クラステンプレート

第二節

18

Page 19: 研究生のためのC++ no.4

19

クラスにもテンプレートの概念を適用できます

Page 20: 研究生のためのC++ no.4

クラステンプレートとは

20

Sample 4-4

Page 21: 研究生のためのC++ no.4

21

そうだ。ベクトルクラスつくろう

Page 22: 研究生のためのC++ no.4

sample 4-4-1/Vector3.h

class Vector3

{

public:

Vector3() … { … }

Vector3(float x, float y, float z) … { … }

static float dot(Vector3 a, Vector3 b) { … }

float x, y, z;

};

Vector3 operator +(Vector3 a, Vector3 b) { … }

22

クラステンプレートとは

Sample 4-4

前回作ったベクトルクラス(の一部)

float以外でも使えるようにしたい

Page 23: 研究生のためのC++ no.4

sample 4-4-2/Vector3.h

template <typename T>

class Vector3

{

(省略)

T x, y, z;

};

23

クラステンプレートとは

Sample 4-4

テンプレートベクトルクラス

template <…>

をクラス定義の前につけると、

クラステンプレートになる.

データ型に依存

しないクラス

Page 24: 研究生のためのC++ no.4

クラステンプレートの特殊化

24

Sample 4-5

Page 25: 研究生のためのC++ no.4

25

関数テンプレートと同じように、クラステンプレート

も特殊化ができます(省略)

Page 26: 研究生のためのC++ no.4

テンプレートのからくり

第三節

26

Page 27: 研究生のためのC++ no.4

テンプレートのからくり

テンプレートの型引数ごとに別個にコードを生成

27

Page 28: 研究生のためのC++ no.4

sample 4-6-1

#include <iostream>

template <typename T> void func() {}

int main()

{

printf("<int> -> %p¥n", func<int>);

printf("<double> -> %p¥n", func<double>);

}

実行結果

<int> -> 0095100F

<double> -> 00951014

28

テンプレートのからくり

関数のアドレスを調べればわかる

func<int>が出現した時点でfunc<int>を コンパイル時に生成

コンパイラ

Page 29: 研究生のためのC++ no.4

まとめ

29

Page 30: 研究生のためのC++ no.4

template <typename T>

void f() { /* ... */ }

template <typename T>

class C { /* ... */ };

30

テンプレート

データ型に依存しない関数・クラスを作る仕組み

template <…> を関数の前につけると 関数テンプレートを定義

template <…> をクラスの前につけると クラステンプレートを定義

Page 31: 研究生のためのC++ no.4

template <typename T>

void f() { /* ... */ }

template <typename T>

class C { /* ... */ };

int main()

{

f<int>();

C<int> c;

}

31

テンプレート引数の指定

f<…> C<…>

でテンプレート引数を 明示的に指定

Page 32: 研究生のためのC++ no.4

言語比較 <ジェネリック編>

おまけ

32

Page 33: 研究生のためのC++ no.4

ジェネリック機能比較

C++ C# Java

実体の生成

タイミング コンパイル時 実行時

コンパイル時にキャストを挿

入し非ジェネリックに変換、

つまり実体は一つ

パフォーマンス ◎

(実体別に最適化) ○

×

(キャストによるオーバーヘッ

ドが発生)

コンパイル後の

コード共有

×

(プログラムサイズが爆発

する原因)

○ ○

(実体は一つしかない)

組み込み型の

ジェネリック引数 ○

(組み込み型の

ジェネリックはク

ラス型のものと

は別に生成)

×

(クラス型のみ○)

33

このページに詳しく書いてあります

Page 34: 研究生のためのC++ no.4

sample 4-7-1/main.cpp

#include <iostream>

template <typename T> class C

{

public:

template <typename U> static void F() {}

};

int main()

{

C<int>::F<double>();

printf("%s¥n", typeid(C<int>).name());

printf("%s¥n", typeid(C<double>).name());

}

実行結果

class C<int>

class C<double>

34

言語比較 <ジェネリック編>

おまけ

C++のジェネリック(テンプレート)

Page 35: 研究生のためのC++ no.4

sample 4-7-2/Program.cs

using System;

class C<T>

{

public static void F<U>() { }

}

class Program

{

static void Main(string[] args)

{

C<int>.F<double>();

Console.WriteLine(typeof(C<int>));

Console.WriteLine(typeof(C<float>));

}

}

実行結果

C`1[System.Int32]

C`1[System.Single]

35

言語比較 <ジェネリック編>

おまけ

C#のジェネリック

Page 36: 研究生のためのC++ no.4

sample 4-7-3/Program.java

実行結果

class C

class C

36

おまけ

Javaのジェネリック

言語比較 <ジェネリック編>

型情報が抜け落ちてる…