13

私は同僚のコードをコードレビューしていて、これを見つけました:

ヘッダー ファイル:

template<class T>
class MyClass
{
  void Execute();
}

Cpp ファイル:

void MyClass<int>::Execute()
{
  // something
}

void MyClass<string>::Execute()
{
  // something else
}

コードは関数を特殊化していますが、テンプレートの特殊化構文を使用していません。正常に動作していると思いますが、有効ですか?

4

4 に答える 4

7

はい、テンプレート クラスのメソッドを特殊化することは完全に有効です。

しかし、あなたの構文は間違っています。次のようにする必要があります: (申し訳ありませんが、template<>最初に が欠落しているとは思いませんでした。そこにあると仮定し、メンバー関数の特殊化について質問していると思いました。)

template<>
void MyClass<int>::Execute()
{
  // something
}
template<>
void MyClass<string>::Execute()
{
  // something else
}

これらをヘッダーで宣言するだけです。ヘッダーにも実装する場合は、それらをマークしinlineて多重定義を防ぐ必要があります。

メソッドを呼び出すときは、その呼び出しに最も適したバージョンが呼び出されます。それ以外の場合は、デフォルト。

あなたの場合、クラスXでテンプレートを特殊化して を呼び出そうとすると、デフォルトの実装もforExecuteの特殊化も提供していないため、リンカー エラーが発生します。ExecuteX

于 2012-08-23T14:54:54.663 に答える
5

質問はすでに回答されていますが、3 つのケースの微妙な違いに注目してみましょう。

ケース 1: 特化

ヘッダ:

template <typename T> struct Foo
{
    void f() { /* stuff */ }
};

template <> void Foo<int>::f();

ソース:

template <> void Foo<int>::f() { /* ... */ }

この場合、Foo<T>::f()は任意の に対して呼び出すことができますT。一般的なケースの定義は、テンプレートから自動生成されます。の定義Foo<int>::f()は提供されているものです。ヘッダーに特殊化があると、テンプレートを使用するのではなく、別のシンボルを検索する必要があることを消費するすべての翻訳単位に警告します。


ケース 2: 定義

ヘッダ:

template <typename T> struct Foo
{
    void f();
};

ソース:

template <> void Foo<int>::f() { /* ... */ }

この場合、のみ Foo<int>::f()使用できます。それ以外の場合はリンカー エラーが発生します。テンプレートには関数の定義がないため、テンプレートを使用するたびに新しいシンボルが発行Foo<int>::f()され、示されている翻訳単位によって提供されるのは 1 つだけです。


ケース 3: 重大な誤り

ヘッダ:

template <typename T> struct Foo
{
    void f() { /* stuff */ }
};

ソース:

template <> void Foo<int>::f() { /* ... */ }

の定義が複数あるため、これは 1 つの定義の規則に違反していますFoo<int>::f()

于 2012-08-23T15:00:46.507 に答える
4

これは、明示的な特殊化の古い構文です。しかし、あなたがまだそれを受け入れるコンパイラを使用していることに驚いています (g++ は 4.0 前後で停止しました)。準拠するには、特殊化の前に を付ける必要がありますtemplate <>

于 2012-08-23T15:00:11.880 に答える
2

タイトルの質問に最初に書かれたとおりに答えるには、絶対に。専門分野にまったく関係のない一連のメンバーを含めることも有効です。

コード内の質問に答えるには、コンパイラのバグのように見えます。template <>が必要です。

于 2012-08-23T15:00:48.533 に答える