スポンサーサイト関数テンプレート

Home > ----- / スポンサー広告 > This Entry 2006-07 / CからC++へ > This Entry [com : 0][Tb : 0]

--------

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

2006-07-24

テンプレート・メタプログラミングの話題を並行して進めると宣言しておきながら放置気味でしたが、カテゴリ「CからC++へ」でテンプレートの話ができるタイミングをある程度うかがっていました。ようやく今回から、「CからC++へ」でもテンプレートの話題に入ります。

テンプレートの具体的な話をする前に、引数として渡された2つの値を比較して、大きい方の値を返す max 関数について考えてみましょう。

int max(int a, int b)
{
  return a < b ? b : a;
}

のように非常に簡単な関数です。次に、この関数のlong型版とdouble型版を作ってみましょう。

long max(long a, long b)
{
  return a < b ? b : a;
}

double max(double a, double b)
{
  return a < b ? b : a;
}

やはり簡単です。同じようにして、long double版とか、unsigned int版などもできそうです。それどころか、< 演算子で大小比較さえできれば、文字列クラスのようなものでさえ同じように書けるはずです。

簡単なのはよいのですが、では、同じものをこれだけの回数書くのがよいのでしょうか?コピー&ペーストすればよいので問題なしですか?
そんなことはないですね。この関数はたまたま簡単ですが、もっと複雑なものもあるでしょうし、新しいユーザー定義型に対応させるたびにコピー&ペーストが必要になります。こんなやり方では、第一保守性が悪すぎます。

では、マクロを使うのはどうでしょう。次のようにです。

#define max(a, b) ((a) < (b) ? (b) : (a))

これならどんな型にでも適用できますが、よく知られているように、副作用のある式を実引数にしたときに問題がありますし、こんなマクロを定義してしまうと、どんな名前空間だろうと、どんなクラスのメンバ関数だろうと、そんなことはお構いなしに置換してしまいます。

そこで、この悩みを一気に解決してくれるのが関数テンプレートというわけです。関数テンプレートを使えば、中身の処理は同じなのに、引数の型だけが異なる関数をまとめて定義することができます。

template <typename T>
T max(T a, T b)
{
  return a < b ? b : a;
}

上の関数テンプレートでは、T というパラメータ(テンプレート仮引数)を使うことで、どんな型の引数が渡されたとしても、a < b ? b : a を返すことを表しています。そして、実際に max 関数を呼び出す処理が(コンパイル時に)現れた時点で、実引数の型に応じた関数の実体が作られます。

ところで、関数テンプレートにも若干の注意点があります。まず第一に、実引数の型の種類だけ関数の実体が作られますので、何も考えずに使っていると、コードの肥大化を招きます。

第二に、関数テンプレートでは、実引数を仮引数の型に合うように暗黙の変換が行われることがかなり制約されます。例えば、char型やshort型はint型用のものを呼び出してくれればよいと思っても、char型用もshort型用も列挙型用も、全部実体が生成されてしまうのです。

第三に、今回の max 関数のように、同じテンプレート仮引数で指定した型の(関数の)仮引数を複数持つ関数の場合、それらに渡す実引数は全て同じ型でなければなりません。具体的には、a がint型で b がlong型のような場合、(仮にint型とlong型のサイズが同じであったとしても)関数の実体を作ることができずにコンパイルエラーが発生してしまいます。

こうした制約は、必ずしも不便なものということではありません。しっかりとその特徴を把握した上で関数テンプレートを定義すれば、曖昧な部分のない堅牢なコードが書けるはずです。

Comment

Post a Comment









管理者にだけ表示を許可

Trackback

http://cppemb.blog17.fc2.com/tb.php/95-d5308b0d

C++と組み込み環境 | Page Top▲

New >>
関数テンプレートの特殊化
<< old
型識別
ブログ内検索
RSSフィード
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。