0
template <typename T> struct s
{

};

template <> struct s<MyClass *>
{

};

... in main function
struct s<MyClass*> obj;

上記のコードはコンパイルされますが、完全な特殊化で何ができるのか本当にわかりません

template <> struct s<MyClass *>
{

};

次のようなポインター変数(定数でも静的でもない)を追加できません

template <> struct s<MyClass *obj > // ERROR
{

};

では、上記の専門化のポイントは何ですか? MyClass *「匿名」ポインターを使用できません

4

2 に答える 2

1

次のようなポインタ変数(定数でも静的でもない)を追加できません

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つの重要なアプリケーションは、特性を定義することです。これについては、読みたいと思うかもしれません。

于 2013-03-02T14:17:57.760 に答える
0

テンプレートを (暗黙的または明示的に) インスタンス化するときは、型を指定します。

s<int> s1;
s<float> s2;
s<MyClass> s3;

これらのオブジェクトは、それぞれ、、およびsT推定されるテンプレートのインスタンス化になります。たとえば、実際に次のように定義されている場合:intfloatMyClasss

template <typename T> struct s {
  T x;
};

次に、オブジェクトにはtypes1という名前のメンバーがあり、typeという名前のメンバーがあり、 typeという名前のメンバーがあります。xints2xfloats3xMyClass

あなたが与えた明示的な特殊化のポイントは、次のようsに、テンプレートパラメーターに渡される型が a である場合の異なる実装を提供することMyClass*です。

s<MyClass*> s4;

たとえば、次のような明示的な特殊化を考えてみましょう。

template <> struct s<MyClass*>
{
  int x;
};

オブジェクトs4は、テンプレート引数が であるにもかかわらず、タイプMyClass*のメンバーが呼び出されます。「テンプレートの引数の型がの場合、構造体はメンバーを持ちます」と具体的に述べました。xintMyClass*int x

このオブジェクトは、より一般的なバージョンではなく、s4の明示的な特殊化を使用します。sテンプレート引数がMyClass*.

于 2013-03-02T14:13:58.023 に答える