関数テンプレートの使い方 - C++ プログラミング
PROGRAM
関数テンプレートを使う
C++ では、任意の型に対して同じ処理を実装できる "関数テンプレート" という機能があります。
これを使用することで、任意の型を引数に取る "テンプレート関数" を定義して使うことができます。
たとえば 2 つの引数の中から最大値を選ぶ関数を作りたい場合、それの int 用と double 用を作りたいとき、関数のオーバーロードでは、ほとんど同じ実装を持った関数を 2 つ作る必要がありました。
// 関数のオーバーロードの場合、ほとんど同じプログラムを何度も書く必要がある場合がありました。
int max(int a, int b)
{
return (a > b ? a : b);
}
double max(double a, double b)
{
double (a > b ? a : b);
}
マクロを使うとひとつの実装でも済みますが、マクロはあくまでもコード置換の方法なので、定義の仕方が独特だったり、コンパイルエラーやデバッグ時にエラーを追うのが面倒です。
// マクロは記載が独特なのと、あくまでもソースコードの置換なので、コンパイルエラーや実行時エラーの対応が難しくなりがちです。
#define MAX int max(a, b) \
(a > b ? a : b)
そんなときに関数テンプレートを使うと、マクロよりも簡単に、複数の型に対応したプログラムを用意することができます。
なお、関数ではなくクラスについて似たいようなことをしたい場合は クラステンプレート という機能を使います。
テンプレート関数を定義する
関数テンプレートでは、冒頭で template キーワードを使って関数を定義します。template キーワードでは <> を使って、その中で class キーワードに続けて、関数内で登場するデータ型を、任意の名前で指定します。
複数のデータ型を扱いたい場合は、class キーワードとデータ型で表す型パラメータを必要な数だけカンマ区切りで指定します。
// 関数テンプレートを使うと、扱うデータ型だけが違う関数を 1 つだけ定義するだけで済みます。
template<class T>
T max(T a, T b)
{
return (a > b ? a : b);
}
この template キーワードで始まる行に、後は続けて普段通りの関数を実装するだけで、template キーワードのところで指定した型名(ここでは T という名前)を使って、関数を定義することができます。
class キーワードで定義した名前は、変数名ではなくデータ型名なので、この名前はデータ型のところに登場するのが、普段の関数定義とは感覚が違ってくるところです。
テンプレート関数を使う
定義したテンプレート関数は、任意の型の変数を渡すだけですぐに使い始められます。
// たとえばこのような変数があったとして…
int i1 = 10;
int i2 = 5;
double d1 = 8.3;
double d2 = 15.5;
// これらを使ってテンプレート関数を直ぐに呼び出せます。
int i = max(i1, i2);
int d = max(d1, d2);
たとえば、今回の max テンプレート関数であれば、2 つの引数と戻り値の型が T として定義されているので「2 つの引数を同じ型で渡して、戻り値を引数と同じ型で受ける」というところにだけ注意すれば、引数が int の場合とか double の場合とかを明示しなくて大丈夫です。
指定する引数がミスマッチだったりすると、コンパイラが適格にエラーを出してくれるのも嬉しいところです。
なお、テンプレート関数は、同じ名前の通常関数などと一緒に共存できます。
ある関数が呼び出されようとしたときに、コンパイラはまず、関数名と引数の型が正確に一致する通常関数がないかを調べ、あればそれを呼び出すことにします。このとき、型の暗黙変換は考慮されません。
それがない場合は、関数名と引数の型が正確に一致するテンプレート関数がないかを調べ、あればそれを呼び出すことにします。このときも、型の暗黙変換は考慮されません。
これらに正確に一致する関数がなかった時、コンパイラは暗黙型変換も考慮して、オーバーロードされた関数の中から適切なものを選んで呼び出します。
[ もどる ]