メンバ関数テンプレートの部分特殊化 vs オーバーロード
メンバ関数テンプレートの挙動を、とある引数に対してのみ変更したい場合の選択肢としてテンプレートの特殊化とオーバーロードがあります。
struct ClassA {
// メンバ関数テンプレート
template<typename T> void Func(T value) {
...
}
// テンプレートの特殊化
template<> void Func<int>(int value) {
...
}
// オーバーロード
void Func(float value) {
...
}
};
優柔不断な自分はここで、テンプレートの特殊化にするかオーバーロードにするか悩みました。
で、それぞれのメリット・デメリットを考えてみました。
テンプレートの特殊化
メリット
・ClassAを定義しているヘッダファイルを変更することなく、新しい特殊化を追加できる。
例えば、
ファイル ClassA.h
struct ClassA {
// テンプレートメンバ関数
template<typename T> void Func(T value) {
...
}
};
ファイル ClassAUserImpl.cpp
#include "ClassA.h"
// テンプレートの特殊化
template<> void ClassA::Func<int>(int value) {
...
}
ということが可能で、特殊化に関しては「クラスの使用者側で必要になり次第勝手に(自己責任で!)特殊化してください」ということができます。
これはメリットであると共にデメリットにもなりうるかもしれません。
デメリット
・古いコンパイラだとテンプレートの部分特殊化を使用できない。
オーバーロード
メリット
・テンプレートではないのでメンバ関数の実装をインラインに書く必要がない。
・C++の基本なので読みやすい(?)
デメリット
・特になし
ちなみに、テンプレートの特殊化とオーバーロードを同じ型に対して同時に行うとどうなるのかと思って試してみたところ、オーバーロードが優先されました。(VC7.1)