web-dev-qa-db-ja.com

テンプレート化されたクラスからの単一メソッドのテンプレート特化

テンプレートクラスを含む次のヘッダーが少なくとも2つの.CPPファイル、このコードは正しくコンパイルされます。

template <class T>
class TClass 
{
public:
  void doSomething(std::vector<T> * v);
};

template <class T>
void TClass<T>::doSomething(std::vector<T> * v) {
  // Do something with a vector of a generic T
}

template <>
inline void TClass<int>::doSomething(std::vector<int> * v) {
  // Do something with a vector of int's
}

ただし、特殊化メソッドのインラインに注意してください。メソッドが複数回定義されているため、リンカーエラー(VS2008ではLNK2005)を回避する必要があります。私の知る限り、完全なテンプレートの特化は単純なメソッド定義と同じだからです。

それで、inlineを削除するにはどうすればよいですか?コードを使用するたびにコードを複製しないでください。 Googleを検索して、SOのいくつかの質問を読んで、提案されたソリューションの多くを試しましたが、正常にビルドできませんでした(少なくともVS 2008ではそうではありません)。

ありがとう!

80
Chuim

単純な関数と同様に、宣言と実装を使用できます。ヘッダー宣言を入力します。

template <>
void TClass<int>::doSomething(std::vector<int> * v);

そして、実装をcppファイルの1つに入れます。

template <>
void TClass<int>::doSomething(std::vector<int> * v) {
 // Do somtehing with a vector of int's
}

インラインを削除することを忘れないでください(このソリューションが機能しないことを忘れて、思っていました:))。 VC++ 2005で確認

65
maxim1000

特殊化定義をCPPファイルに移動する必要があります。関数がテンプレートとして宣言されていない場合でも、テンプレートクラスのメンバー関数の特殊化は許可されます。

4
BostonLogan

キーワードをインラインで削除する理由はありません。
とにかくコードの意味は変わりません。

2
Martin York

何らかの理由でインラインを削除する場合、maxim1000のソリューションは完全に有効です。

あなたのコメントでは、インラインキーワードは、彼のすべてのコンテンツを持つ関数が常にインライン化されることを意味すると信じているようですが、実際にはコンパイラの最適化に非常に依存しています。

C++ FAQ からの引用

関数がインラインであることを指定する方法はいくつかありますが、そのうちのいくつかはインラインキーワードを使用し、その他は使用しません。関数をインラインとして指定する方法に関係なく、コンパイラーは無視することができます。コンパイラーは、インラインとして指定された関数を呼び出す場所の一部、すべて、またはまったくインライン展開しない場合があります。 (それが絶望的に​​漠然としているように思われても落胆しないでください。上記の柔軟性は実際には大きな利点です。適切なコンパイラオプション。)

そのため、その関数が実際に実行可能ファイルを膨張させることがわかっている場合、または他の理由でテンプレート定義ヘッダーから削除したくない場合を除き、実際に何の害もなしに残すことができます

2
Triskeldeian