C++では、特殊化(specialization)、明示的特殊化(explicit specialization)、部分的特殊化(partial specialization)がある。
このうち、部分的特殊化というのは、全く違う概念である。明示的特殊化に似ているので特殊化という名前がついているものの、あくまで部分的であるので、依然としてテンプレートである。
template < typename T > struct X ; template < typename T > struct X< T * > ;
しかし、明示的特殊化は、完全に特殊化されている。
template < typename T > struct X ; template < > struct X< int > ;
また、特殊化とは、暗黙的に実体化(instantiation)されたものと、明示的に特殊化されたものとの総称である。部分的特殊化とは、特殊化という名前が紛らわしいだけの別物である。
もう少し分かりやすい別の用語を選べなかったものか。
こんなに古い記事にコメントするのもどうかと思うのですが、テンプレートについて学習している人がハマる可能性があるので、異なる意見を書きます。
ReplyDelete>また、特殊化とは、暗黙的に実体化(instantiation)されたものと、明示的に特殊化されたものとの総称である。
私もおそらく多くの読者と同様、江添氏の多くの記事をたいへん参考にさせて頂き非常に感謝しています。
ただ、この記述だけは、テンプレートの理解に支障を来し、多少余分な時間がかかりました。
プライマリー・テンプレート、部分的特殊化、特殊化はすべて「定義」です。
例示されているものは「宣言」なので定義がないですね。でも、別途定義が必要です。
しかし、実体化は定義ではなく、他のところで定義されたテンプレートを使うものです。
実体化した時に使われる定義は、プライマリー・テンプレート、部分特殊化、特殊化のどれかが実体化で与えたテンプレート・パラメータによって選択されます。
例えば、特殊化定義をコメントアウトしても、相変わらず実体化でき、その時はプライマリー・テンプレートが選択されます。
普通のクラスの対応するものと並べてみます。
プライマリー・テンプレート定義(これは当然ですが普通のクラスには対応するものはないです)
template class foo {};
部分特殊化テンプレート定義(これもテンプレートのままなので普通のクラスに対応しないです)
template class foo {};
明示的特殊化定義とクラス定義
template<> class foo {};
class bar {};
明示的特殊化宣言とクラス宣言
template<> class foo;
class bar;
実体化とクラスの使用
foo foo_instance;
bar bar_instance;
クラスを「定義すること」と「使うこと」は全く異なりますね。
同様に特殊化テンプレートを定義することとそれを使う(実体化する)ことは全く異なります。
>部分的特殊化とは、特殊化という名前が紛らわしいだけの別物である。
江添氏の言うとおり、部分特殊化されたテンプレートはテンプレートで、特殊化されたテンプレートは既にテンプレートではないのにどちらもテンプレートっぽく感じるので紛らわしいですね。
テンプレートを特殊化したものは普通のクラスと事実上同じであることを知っていれば良いだけかも知れません。
friend指定では相変わらずテンプレートとして含むことができるので、用語的には「右辺値参照」と同様ベストではないけど、ワーストではないし、より妥当な名称がないので許容するしかないって感じでしょうか?
ああ、<>で囲った部分が消えてます。
ReplyDeleteHTMLの文法を知らないので、適切に記述できません。
役に立たないコメントに成り下がってしまった。orz
あらら、<typename T>が消えちゃってます。
ReplyDelete修正修正。
プライマリー・テンプレート定義(これは当然ですが普通のクラスには対応するものはないです)
template<typename T> class foo {};
部分特殊化テンプレート定義(これもテンプレートのままなので普通のクラスに対応しないです)
template<typename T> class foo<T*> {};
明示的特殊化定義とクラス定義
template<> class foo<int> {};
class bar {};
明示的特殊化宣言とクラス宣言
template<> class foo<int>;
class bar;
実体化とクラスの使用
foo<int> foo_instance;
bar bar_instance;