テンプレートを使用する場合、ますます長いコンパイル時間をどのように処理しますか?


13

私はVisual Studio 2012を使用していますが、ユニットテストでこれらのパーツをモックオブジェクトに置き換えることができるように、「継ぎ目」を導入するためにクラスパラメーターにテンプレートパラメーターを追加した場合があります。

通常、C ++でどのようにシームポイントを導入しますか。テンプレートパラメーターを使用して、暗黙的なインターフェースとのいくつかの基準に基づいてインターフェースを使用したり、混合したりしますか?これを求める理由の1つは、1つのC ++ファイル(テンプレートファイルを含む、他のテンプレートも含む可能性がある)をコンパイルすると、開発者のマシンで約5〜10秒かかるオブジェクトファイルが生成されるためです。 。

VSコンパイラは、私が理解している限り、テンプレートをコンパイルするのに特に高速ではありません、テンプレートインクルードモデルのために(実際にテンプレートの定義を間接的に使用するすべてのファイルに含め、変更するたびにそのテンプレートを再インスタンス化する可能性がありますそのテンプレートとは何の関係もない)コンパイル時間に問題がある可能性があります(インクリメンタルコンパイルを行う場合)。

テンプレートを操作するときに、コンパイル時間をインクリメンタルに(そしてそれだけでなく)処理する方法は何ですか(より良い/より速いコンパイラに加えて:-))。


1
@RobertHarvey依存関係の注入は、テンプレートパラメーターを使用して行われます。これらをインスタンス化する本番コードでは、コンパイル時間が遅くなります。
ギタ

5
C ++ 11を使用していますか?en.wikipedia.org/wiki/C%2B%2B11#Extern_templateを
mike30

2
Andrei Alexandrescuが「現代のC ++デザイン」を書いているので、多くのC ++プログラマーは、すべてのものにテンプレートを使用し、コンパイラーに可能な限り処理させる必要があると考えています。それは通常、あなたが説明しているそれらの効果につながります。以前(そして現在も他の言語を使用しているプログラマーにとって)、テンプレートを使用せず、ランタイムメカニクスで依存性注入のようなものを処理することは絶対に問題ありませんでした。 )。正直に言って、ロバートは100%正しいと思います。
ドックブラウン

1
@Ghita:テンプレートメタプログラミングを使用したIMHOは、多くの場合、時期尚早な最適化の1つの形式です(場合によっては単にやりすぎ)-同等の要件を持つSTLのようなライブラリを作成しない限り。コンパイル時間を長くし、保守性を低くし、理解しにくいエラーメッセージを大量に取得することで、パフォーマンスとトレードオフの関係があります。「外部テンプレート」を使用すると、短期的にはあなたを助けるかもしれませんが、もし私があなたの靴にいたら、長期的な改善も考えます。
ドク・ブラウン

4
@DocBrown。逆に、ビルドのパフォーマンスを向上させるためにテンプレートを避けることは、時期尚早な最適化と言えます。テンプレートは、多くの問題の理想的な抽象化です。
mike30

回答:


9

場合は、テンプレートのパラメータのみが有限(および小)値のセットを取ることができる、あなたがソース・ファイルにその定義を移動し、使用することができます明示的なインスタンスを

たとえば、中にaaa.hあなただけのテンプレート関数を宣言fしてg

template <int n>
int f();

template <class T>
void g(int a);

仮定nテンプレートパラメータのみ1、3、6であることができ、Tテンプレートパラメータのみとすることができるintlongvoid *

次に、これらを次のaaa.cppように定義します。

template <int n>
int f()
{
    ...
}

template <class T>
void g(int a)
{
    ...
}

template int f<1>();
template int f<3>();
template int f<6>();

template void g<int>(int a);
template void g<long>(int a);
template void g<void *>(int a);

このようにして、コンパイラはコンパイル時に指定されたパラメータのテンプレートをインスタンス化しますaaa.cpp。クライアントコードをコンパイルするとき、定義がどこかに存在すると仮定し、リンカーがそれを処理します。

#include "aaa.h"

int main()
{
    f<1>();
    f<3>();
    f<6>();

    g<int>(5);
    g<long>(5);
    g<void *>(5);
}

テンプレートクラスを明示的にインスタンス化することもできます。欠点は、あなたが使用できないということですfか、g他のテンプレートパラメータを持ちます。

#include "aaa.h"

int main()
{
    f<5>();
}

結果として

undefined reference to `int f<5>()'

少数の複雑なクラスが少数(<10)の整数テンプレートパラメーターセットに依存するプロジェクトでこの手法を使用し、コンパイル時間を大幅に短縮しました(クライアントコードのコンパイル時にコンパイラーが複雑なテンプレート定義を解析する必要がないため) 。もちろん、実際のコードによっては、改善度が低くなる場合があります。


2

同様の問題に対して奇妙な解決策を使用したことがあります。STLを含めると、ソースファイルごとにコンパイル時間が数秒になります-どんなに小さくても。したがって、すべてのソースファイルを1つのマスターファイルに含め、ファイルごとのコンパイル時間はほとんど変更しませんでした。つまり、コンパイルするファイルが1つしかないため、20倍以上の速度になりました。

設計をきれいに保つために、メイクファイルを維持し続けましたが、実際に使用したことはありませんでした(検証が機能することを除いて)。


0

以前は大きなタスクを実行して、プリコンパイル済みヘッダーとプリコンパイル済みテンプレートを一晩作成し、翌日にはそれらに対してビルドしていました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.