研究生のためのc++ no.4
TRANSCRIPT
C++ For Researchers 研究生のためのC++
企画・立案 難波知宏
テンプレート
第四回
2
関数テンプレート
第一節
3
関数テンプレートとは
4
Sample 4-1
5
そうだ、max関数を作ろう
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 を返す
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
従来のプログラム
データ型が違うだけで
同じ処理なのに、
別々に記述
何とかして一つに
まとめられないか?
8
テンプレートで
できますよ
sample 4-1-2
template <typename Type>
Type max(Type x, Type y)
{
return (x > y) ? x : y;
}
9
関数テンプレートとは
Sample 4-1
テンプレートを使って一つにまとめる
データ型に依存
しない関数
template <…>
を関数の前につけると、
関数テンプレートになる.
テンプレート引数の明示指定
Sample 4-2
10
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のどちらに
したらいいかわからない!
コンパイラ
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
<…>でテンプレート引数の型を指定すればよい。
実は、テンプレート引数
が省略された場合、
コンパイラが自動で
推論しているんだよね
コンパイラ
関数テンプレートの特殊化
13
Sample 4-3
14
string型でもmax関数が動くようにしたい
15
そんでもって
string型の場合は、長さが大きい方を返したい
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
従来のプログラム
期待通りに
ならない
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*
の場合は、例外的にこの
関数が呼ばれる
クラステンプレート
第二節
18
19
クラスにもテンプレートの概念を適用できます
クラステンプレートとは
20
Sample 4-4
21
そうだ。ベクトルクラスつくろう
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以外でも使えるようにしたい
sample 4-4-2/Vector3.h
template <typename T>
class Vector3
{
(省略)
T x, y, z;
};
23
クラステンプレートとは
Sample 4-4
テンプレートベクトルクラス
template <…>
をクラス定義の前につけると、
クラステンプレートになる.
データ型に依存
しないクラス
クラステンプレートの特殊化
24
Sample 4-5
25
関数テンプレートと同じように、クラステンプレート
も特殊化ができます(省略)
テンプレートのからくり
第三節
26
テンプレートのからくり
テンプレートの型引数ごとに別個にコードを生成
27
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>を コンパイル時に生成
コンパイラ
まとめ
29
template <typename T>
void f() { /* ... */ }
template <typename T>
class C { /* ... */ };
30
テンプレート
データ型に依存しない関数・クラスを作る仕組み
template <…> を関数の前につけると 関数テンプレートを定義
template <…> をクラスの前につけると クラステンプレートを定義
template <typename T>
void f() { /* ... */ }
template <typename T>
class C { /* ... */ };
int main()
{
f<int>();
C<int> c;
}
31
テンプレート引数の指定
f<…> C<…>
でテンプレート引数を 明示的に指定
言語比較 <ジェネリック編>
おまけ
32
ジェネリック機能比較
C++ C# Java
実体の生成
タイミング コンパイル時 実行時
コンパイル時にキャストを挿
入し非ジェネリックに変換、
つまり実体は一つ
パフォーマンス ◎
(実体別に最適化) ○
×
(キャストによるオーバーヘッ
ドが発生)
コンパイル後の
コード共有
×
(プログラムサイズが爆発
する原因)
○ ○
(実体は一つしかない)
組み込み型の
ジェネリック引数 ○
○
(組み込み型の
ジェネリックはク
ラス型のものと
は別に生成)
×
(クラス型のみ○)
33
このページに詳しく書いてあります
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++のジェネリック(テンプレート)
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#のジェネリック
sample 4-7-3/Program.java
実行結果
class C
class C
36
おまけ
Javaのジェネリック
言語比較 <ジェネリック編>
型情報が抜け落ちてる…