次のようなポインタ変数(定数でも静的でもない)を追加できません
template <> struct s<MyClass *obj > // ERROR
[...]
あなたはおそらくここで誤解を持っています。非型テンプレートパラメータとしてユーザー定義クラスのインスタンスへのポインタを提供するユースケースに関心がある場合、これはテンプレートの特殊化とは関係ありません。
特に、 C++11標準の段落14.3.2/1に従って、クラスのグローバルインスタンスへのポインタをテンプレート引数として指定できることを考慮してください。
非型、非テンプレートのテンプレートパラメータのテンプレート引数は、次のいずれかである必要があります。
—整数型または列挙型の非型テンプレートパラメーターの場合、テンプレートパラメーターの型の変換された定数式(5.19)。また
—型以外のテンプレートパラメータの名前。また
—静的ストレージ期間と外部または内部リンケージを持つオブジェクト、または関数テンプレートと関数テンプレートIDを含み、非静的クラスメンバーを除く外部または内部リンケージを持つ関数のアドレスを指定する定数式(5.19) 。 &id-expressionとしての括弧を無視します。ただし、名前が関数または配列を参照している場合は&を省略でき、対応するtemplate-parameterが参照の場合は省略できます。また
[...]
これはおそらくあなたが達成しようとしていたことです:
struct MyClass { };
MyClass c;
template<MyClass* p>
// ^^^^^^^^ Non-type template argument
struct s
{
// Possibly work with p
};
int main()
{
s<&c> obj;
}
テンプレートの特殊化について:
作成したコードに関して、プライマリテンプレートはすべてのタイプを処理します。
template <typename T> struct s
{
// Definition...
};
そして、この明示的な特殊化(これは「合計」特殊化ではなく技術名です)を使用すると、プライマリテンプレートのインスタンス化に使用される引数が次の場合にプライマリテンプレートのコンテンツを再定義できますMyClass*
。
template <> struct s<MyClass *>
{
// Definition when the template argument is `MyClass*`
};
たとえば、次のようにすることができます。
struct MyClass { };
template <typename T> struct s
{
void print() { cout << "Primary template!" << endl; }
};
template <> struct s<MyClass *>
{
void print() { cout << "Specialization for MyClass*!" << endl; }
};
int main()
{
s<int> obj;
obj.print(); // Will print "Primary template!"
s<MyClass*> obj;
obj.print(); // Will print "Specialization for MyClass*!"
}
また、特殊なテンプレートの定義は、プライマリテンプレートの定義とは完全に異なる可能性があることに注意してください。
template <typename T> struct s
{
void print() { cout << "Primary template!" << endl; }
};
template <> struct s<MyClass *>
{
void greet() { cout << "Specialization for MyClass*!" << endl; }
};
int main()
{
s<int> obj;
obj.print(); // Will print "Primary template!"
s<MyClass*> obj;
obj.greet(); // Will print "Specialization for MyClass*!"
obj.print(); // ERROR! s<MyClass*> has no `print()` member function
}
もちろん、これはクラステンプレートの特殊化がどのように機能するかの一例にすぎません。プライマリテンプレートと特殊テンプレートの定義を私が行った方法で区別するのに役立つものは何もありません。
ただし、これには多くの実際のユースケースが存在します。たとえば、一般的なアルゴリズムは、特定のタイプに対して完全に異なる方法で最適化および書き換えられる場合があります。
テンプレートの特殊化のもう1つの重要なアプリケーションは、特性を定義することです。これについては、読みたいと思うかもしれません。