27

多くのテンプレート化されたクラスで構成されるライブラリを処理する必要があります。もちろん、それらはすべてヘッダー ファイルに実装されています。今、コンパイル単位のそれぞれと 1 つにライブラリ全体をほとんど含めなければならないという事実から生じる耐え難いほど長いコンパイル時間を短縮する方法を見つけようとしています。

テンプレートにもかかわらず、前方宣言を使用する可能性はありますか? 以下の例の行に沿って何かを試しています。例として、を回避しようとしましたが、が未定義で#include <vector>あるため、リンカーエラーが発生しています。push_back

#include <iostream>

namespace std {
  template<class T>
  class vector {
  public:
    void push_back(const T& t);
  };
}

int main(int argc, char** argv) {
  std::vector<int>* vec = new std::vector<int>();
  vec->push_back(3);
  delete vec;
  return EXIT_SUCCESS;
}

$ g++ fwddecl.cpp
ccuqbCmp.o(.text+0x140): In function `main':
: undefined reference to `std::vector<int>::push_back(int const&)'
collect2: ld returned 1 exit status

プリコンパイル済みヘッダーを 1 回試しましたが、コンパイル時間はまったく変わりませんでした (実際のヘッダーではなく、実際に読み込まれたことを確認しました)。しかし、プリコンパイル済みヘッダーを使用するべきだと皆さんがおっしゃるなら、もう一度試してみます。

更新: STL クラスを前方宣言する価値はないと言う人もいます。vector上記の STL は単なる例であることを強調しておきます。私は実際に STL クラスを前方宣言しようとしているわけではありませんが、それは私が使用しなければならないいくつかのライブラリの、他の重くテンプレート化されたクラスに関するものです。

更新 2:上記の例を実際にコンパイルして適切にリンクする方法はありますか? ローガンは、おそらくでコンパイルされる別のファイルに使用してどこかに-fno-implicit-templates置くことを提案していますが、それでもリンカーエラーが発生します。繰り返しますが、実際に使用しているテンプレート化されたクラスに適用できるように、それがどのように機能するかを理解しようとしています。template class std::vector<int>.cpp-fno-implicit-templatesstd::vector

4

4 に答える 4

22

前方宣言を使用すると、次のことができます。

template <class T> class vector;

vector<whatever>次に、ベクトルを定義せずに (vectorのヘッダー ファイルをインクルードせずに)への参照とポインターを宣言できます。これは、通常の (非テンプレート) クラスの前方宣言と同じように機能します。

特にテンプレートの問題は、(コンパイラが必要なテンプレートをインスタンス化できるように) クラス宣言だけでなく、すべてのメソッド定義がヘッダー ファイルに必要になることです。明示的なテンプレートのインスタンス化 ( with を強制的に使用できます-fno-implicit-templates) は、これに対する回避策です。メソッド定義をソース ファイル (または、 Google スタイル ガイドの例に従って、インクルードする必要のないヘッダー ファイル) に配置し-inl.h、次のように明示的にインスタンス化できます。

template <class int> class vector;

実際にこれを利用する必要はないことに注意してください-fno-implicit-templates。コンパイラーは、リンカーが後でそれを理解することを前提として、定義のないテンプレートのインスタンス化を静かに回避します。また、追加すると(時間のかかるテンプレートだけでなく)すべての-fno-implicit-templatesテンプレートの使用が難しくなるため、お勧めしません。

std::vectorサンプルコードの問題は、真のクラスを宣言していないことです。を含めないことにより<vector>、独自の非標準vectorクラスを作成し、 を定義することはpush_backないため、コンパイラがインスタンス化するものは何もありません。

私はプリコンパイル済みヘッダーを使用して大きな効果を上げました。彼らがあなたを助けなかった理由がわかりません。変更されていないすべてのヘッダーを単一の に入れ、それをプリコンパイルし、ロードされたものまたは同様のものall.hで検証し、個々のヘッダー ファイルはそうではありませんでしたか? (使用方法: を実行する代わりに、実行してから、テキスト エディターで表示し、呼び出しを検索して、どのファイルが読み取られているかを確認します。)straceall.h.pchstraceg++ mytest.ccstrace -o strace.out g++ mytest.ccstrace.outopen(

于 2009-02-17T03:35:56.223 に答える