3

次のように、ヘッダー ファイルのテンプレート化されたクラスと関数でほぼ完全に構成されるライブラリを使用しています。

// foo.h
template<class T>
class Foo {
  Foo(){}
  void computeXYZ() { /* heavy code */ }
};
template<class T>
void processFoo(const Foo<T>& foo) { /* more heavy code */ }

これらのヘッダー ファイルの 1 つをインクルードするたびにコンパイル時間が耐えられないため、これは悪いことです (実際には、各コンパイル ユニットにそれらの多くをインクルードします)。

テンプレート パラメーターとして 1 つまたは 2 つの型しか使用しないため、ライブラリ ヘッダー ファイルごとに、次のような重いコードを含まない宣言のみを含むファイルを作成する予定です。

// NEW: fwd-foo.h
template<class T>
class Foo {
  Foo();
  void computeXYZ();
};
template<class T>
void processFoo(const Foo<T>& foo);

そして、必要なすべてのインスタンス化を作成する 1 つのファイル。そのファイルは、一度だけ個別にコンパイルできます。

// NEW: foo.cpp
#include "foo.h"
template class Foo<int>;
template class Foo<double>;
template void processFoo(const Foo<int>& foo);
template void processFoo(const Foo<double>& foo);

これで、コードにインクルードするだけfwd-foo.hで、コンパイル時間を短縮できます。最後にリンクしますfoo.o

もちろん、欠点は、これらの新しいファイルを自分fwd-foo.hで作成する必要があることです。foo.cppもちろん、これは保守の問題です。新しいライブラリ バージョンがリリースされた場合、それらをその新しいバージョンに適応させる必要があります。他に欠点はありますか?

そして、私の主な質問は次のとおりです。

これらの新しいファイルを、特に元のファイルからfwd-foo.h自動的作成できる可能性はありますfoo.hか? 多くのライブラリヘッダーファイル(おそらく20程度)に対してこれを行う必要があり、特に新しいライブラリバージョンがリリースされ、新しいバージョンでこれを再度行う必要がある場合は、自動ソリューションが最適です。このタスクに使用できるツールはありますか?

編集:

extern追加の質問:この場合、新しくサポートされたキーワードはどのように役立ちますか?

4

4 に答える 4

4

We use lzz which splits out a single file into a separate header and translation unit. By default, it would normally put the template definitions into the header too, however, you can specify that you don't want this to happen.

To show you how you might use it consider the following:

// t.cc
#include "b.h"
#include "c.h"

template <typename T> 
class A {
  void foo () {
    C c;
    c.foo ();
    b.foo ();
  }
  B b;
}

Take the above file and copy it to 't.lzz' file. Place any #include directives into separate $hdr and $src blocks as necessary:

// t.lzz
$hdr
#include "b.h"
$end

$src
#include "c.h"
$end

template <typename T> 
class A {
  void foo () {
    C c;
    c.foo ();
    b.foo ();
  }
  B b;
}

Now finally, run lzz over the file specifying that it places the template definitions into the source file. You can either do this using a $pragma in the source file, or you can use the command line option "-ts":

This will result in the following files being generated:

// t.h
//

#ifndef LZZ_t_h
#define LZZ_t_h
#include "b.h"
#undef LZZ_INLINE
#ifdef LZZ_ENABLE_INLINE
#define LZZ_INLINE inline
#else
#define LZZ_INLINE       
#endif
template <typename T>
class A
{
  void foo ();
  B b;
};
#undef LZZ_INLINE
#endif

And:

// t.cpp
//

#include "t.h"
#include "c.h"
#define LZZ_INLINE inline
template <typename T>
void A <T>::foo ()
          {
    C c;
    c.foo ();
    b.foo ();
  }
#undef LZZ_INLINE

You can then run these through some grep/sed commands to remove the LZZ helper macros.

于 2009-03-17T11:01:26.043 に答える
1

私はかなり長い間、まったく同じ問題に取り組んできました。提案しているソリューションでは、テンプレートクラスを2回定義しています。同じものを(同じ順序で)定義すれば問題ありませんが、遅かれ早かれ問題が発生することになります。

私が思いついたのは、問題を逆に考えることです。実装を専門化していない限り、それは適切に機能します。

2つのマクロを使用しますが、実装ファイルのテンプレート引数を更新する必要はありません(ただし、デフォルトのテンプレート引数をクラスに追加する場合は注意が必要です)。

// foo.h
#define FOO_TEMPLATE template<typename T>
#define FOO_CLASS Foo<T>

FOO_TEMPLATE
class Foo {
  Foo();
  void computeXYZ();
};

// foo_impl.h
#include "foo.h"
FOO_TEMPLATE
FOO_CLASS::Foo(){}

FOO_TEMPLATE
void FOO_CLASS::computeXYZ() { /* heavy code */ }

これを行うことにより、基本的に非テンプレートクラスで行うのと同じように機能します(もちろん、テンプレート関数でも同じことを行うことができます)。

編集:c++0xのexternキーワードについて

c ++ 0xのexternキーワードが役立つと思いますが、すべてを魔法のように解決するわけではありません。

この記事から、

Externテンプレート

テンプレートをインスタンス化するすべてのモジュールは、基本的にオブジェクトコードにそのコピーを作成します。次に、最後の段階ですべての冗長オブジェクトコードを破棄するのはリンカ次第です。これにより、プログラマーの日(または場合によっては空想)を構成する重要な編集-コンパイル-リンクサイクルが遅くなります。このオブジェクトコードのガベージコレクションを回避するために、多くのコンパイラベンダーは、テンプレートの前に配置できるexternキーワードをすでに実装しています。これは、既存の業界慣行を体系化した標準化の事例です(しゃれを意図したもの)。実際には、これは基本的に「これをここでインスタンス化しない」という通知をコンパイラに送信することによって実装されます。

extern template class std::vector;
于 2009-03-17T07:11:17.000 に答える
1

プリコンパイル済みヘッダーを使用してみてください。GCC と MSVC がこの機能をサポートしていることは知っています。ただし、使用法はベンダー固有です。

于 2009-03-17T03:25:27.417 に答える
-1

C++0x は、extern テンプレートに関するコンパイル時の問題を修正します。ただし、あなたが求めることを自動的に行う方法はわかりません。

于 2009-03-17T03:22:59.920 に答える