1

(それほど新しくはない) C++11 標準では、externテンプレートのキーワードが導入されました。その目的は、使用時にテンプレートをインスタンス化するべきではなく、別の翻訳単位でインスタンス化することをコンパイラに伝えることです(したがって、リンク時にインスタンス化が利用可能になります)-少なくともAFAIK。

現在、C++11 より前の時代でも、コンパイルを高速化するために、テンプレート クラスの宣言/定義をそのインスタンス化から分離するために、次のようなものを使用していました。

point.h : クラス定義

template <int dim> struct Point {
  ...
  void foo();
  ...
};

point.cpp : メソッド定義

#include "point.h"
template <int dim>
void Point<dim>::foo() {
  ...
}

point_2d.cpp : クラスのインスタンス化 (2D バージョン)

#include "point.cpp"
template struct Point<2>;

point_3d.cpp : クラスのインスタンス化 (3D バージョン)

#include "point.cpp"
template struct Point<3>;

main.cpp : 2D および 3D ポイントの使用

#include "point.h"
int main(int, char**) {
    Point<2> p;
    p.foo();
}

今私は疑問に思っています:

  • 私たちのアプローチは有効な C++ (03 または 11) コードですか?それともうまくいったのは幸運でしょうか?
  • point.cppC++11 では、 inを含めてmain.cpp宣言することで同じことを実現できextern template <int dim> struct Point;ますか?
4

3 に答える 3

1

私たちのアプローチは有効な C++ (03 または 11) コードですか?それともうまくいったのは幸運でしょうか?

あなたの使用法は有効ですが、標準的ではありません。より一般的な C++98 スタイルでは、明示的なインスタンス化の定義を実装と共にpoint.cppファイルにグループ化します。

// point.h

template <int dim> struct Point {
  ...
  void foo();
  ...
};

 

// point.cpp

#include "point.h"

template <int dim>
void Point<dim>::foo() {
  ...
}

// Now the implementation is available, so this is the time to use it:
template struct Point<2>;
template struct Point<3>;

point.cppC++11 では、 inを含めてmain.cpp宣言することで同じことを実現できextern template <int dim> struct Point;ますか?

ファイルは絶対に使用しない#includeでください。.cpp標準的なスタイルは、関数テンプレートの実装をヘッダー ファイルに配置することです。point.hたとえば、point.hpp.

Point<4>C++11 によって追加された利点は、コンパイル時間が短縮され、暗黙的な特殊化によっても使用できることです。ただし、特殊化されたヘッダーに実装を配置しても、externコンパイルは高速化されずPoint<2>Point<3>.

文字通り言うことはできませんextern template <int dim> struct Point;。ヘッダーには、すべての特殊化をリストする必要があります。

extern template struct Point<2>;
extern template struct Point<3>;

すべての専門化を別の場所に委譲することが、exportテンプレートの本来の目的でした。これは C++98 の機能であり、実装が難しすぎることが判明したため、C++11 標準から削除されました。

于 2015-01-07T00:39:48.730 に答える
1

C++ 11 は、テンプレートをインスタンス化しないようexternにコンパイラに指示するために使用しており、構文は、質問で提案されている構文とは異なり、具象型を使用しています。

extern template struct Point<2>; 

C++03 では、コンパイラは変換単位で監視するたびにテンプレートをインスタンス化する必要がPoint<2>あり、C++11 では extern キーワードと組み合わせると、テンプレートをインスタンス化してはならないことを認識しています。

あなたの質問に対して、C++03 で行ったことは、テンプレートの定義を別のヘッダー ファイル (cpp接尾辞付き、以下を参照) に分離することでした。そのアプローチは C++11 でも機能します。

#include "point.ipp"

extern template struct Point<2>; // instantiated elsewhere

int main(int, char**) {
    Point<2> p;
    p.foo();
}

主観的には、cppテンプレート ヘッダー ファイルのサフィックスも嫌いなので、注意してもらいたいと思います。特にcppファイルが別のcppファイルに含まれているのを見ると、混乱し、誤解を招きます。 ファイル拡張子としてorをそれぞれおよび と組み合わせて

使用​​することを検討してください。ファイルに特定のテンプレートの定義/実装が含まれていることがより明確になります。ippixxhpphxx

于 2014-03-22T09:54:59.343 に答える