私はVisual Studio 2012を使用していますが、ユニットテストでこれらのパーツをモックオブジェクトに置き換えることができるように、「シームポイント」を導入するためにテンプレートパラメーターを「ちょうど」クラスに追加したケースがあります。
通常、C++でシームポイントをどのように導入しますか?テンプレートパラメーターを使用して、インターフェイスを使用するか、いくつかの基準に基づいて暗黙的なインターフェイスと混合することもできますか?これを尋ねる理由の1つは、単一のC++ファイル(テンプレートファイルを含み、他のテンプレートも含む可能性がある)をコンパイルするときに、開発者のマシンで約5〜10秒かかるオブジェクトファイルが生成されるためです。 。
VSコンパイラーは、私が理解している限り、テンプレートのコンパイル速度もそれほど速くありません。また、テンプレートインクルードモデル(実際には、テンプレートのdefinitionを間接的に使用するすべてのファイルに含め、場合によっては再利用します)そのテンプレートとは何の関係もない何かを変更するたびに、そのテンプレートをインスタンス化します)(インクリメンタルコンパイルを行う場合)コンパイル時間に問題が発生する可能性があります。
テンプレートを操作するときのインクリメンタルな(そしてそれだけではない)コンパイル時間を処理する方法は何ですか(より優れた/より速いコンパイラに加えて:-))。
Ifテンプレートパラメータは有限の(そして小さな)値のセットしか想定できない場合、ソースファイルでそれらの定義を移動し、 明示的なインスタンス化 。
たとえば、aaa.h
では、テンプレート関数f
およびg
のみを宣言します。
template <int n>
int f();
template <class T>
void g(int a);
n
テンプレートパラメーターは1、3、6のみで、T
テンプレートパラメーターはint
、long
およびvoid *
のみであると想定します。
次に、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)整数テンプレートパラメーターのセットに依存するプロジェクトでこの手法を使用し、コンパイル時間を大幅に削減しました(クライアントコードをコンパイルするときにコンパイラーが複雑なテンプレート定義を解析する必要がないため)。 。もちろん、実際のコードによっては、改善が少ない場合があります。
かつて私が同様の問題に奇妙な解決策を使用した場合:STLを含めると、コンパイル時間がソースファイルごとに数秒のようになりました-どんなに小さくても。したがって、すべてのソースファイルを1つのマスターファイルに含め、ファイルごとのコンパイル時間はほとんど変更されませんでした...コンパイルするファイルが1つしかないので、20倍以上のスピードアップを意味しました。
デザインをクリーンに保つために、私はメイクファイルを維持し続けましたが、実際にそれを使用したことはありません(動作することを確認する場合を除いて)。
私たちは、プリコンパイルされたヘッダーとプリコンパイルされたテンプレートを一晩で構築し、次の日にそれらに対して構築するという大きなタスクを開始していました。