11

テンプレート メタプログラム (TMP) が与えられた場合、C++ コンパイラは、インスタンス化されたクラスの数をカウントするビルド統計を生成しますか? または、この番号を自動的に取得する他の方法はありますか? たとえば、偏在階乗の場合

#include <iostream>

template<int N> struct fact { enum { value = N * fact<N-1>::value }; };
template<> struct fact<1> { enum { value = 1 }; };

int main()
{
    const int x = fact<3>::value;
    std::cout << x << "\n";
    return 0;
}

数値 3 を取得したいと思います (fact<3>、fact<2>、および fact<1> がインスタンス化されているため)。もちろん、この例は些細なことですが、Boost.MPL などを使い始めると、コンパイル時間が本当に爆発的に増加します。隠しクラスのインスタンス化がどの程度の原因なのかを知りたいです。私の質問は主に Visual C++ に関するものですが、gcc に関する回答もいただければ幸いです。

編集: Visual C++ に対する私の現在の非常に脆弱なアプローチは、Stephan T. Lavavej のビデオ/d1reportAllClassLayout の 1 つからコンパイル スイッチを追加し、出力ファイルで grep + ワード カウントを実行することですが、(a) コンパイル時間が大幅に増加し、(b)正規表現を 100% 正しくすることは困難です。

4

3 に答える 3

8

インスタンス化するときに各クラス テンプレートの名前を出力するように、GCC に1 行の変更を加えました。フラグなしで C++ フロントエンドcc1plusを直接呼び出して、関数テンプレートに対して同じものを取得することができます。-quiet

私はまだそれを適切な GCC オプションに変えていません。それは私自身のソース ツリーの単なるハックです。代わりにプラグインとして実装することを考えていますが、TODO リストの一番上にはありません。

于 2012-07-09T22:33:01.233 に答える
2

もちろん、これを行う移植可能な方法はありません。

ほとんどのコンパイラには、ハックな方法があります。MSVC 用のものは既に見つかりました。gcc の場合、おそらく gccxml を使用できます。または、オープン ソース コンパイラ (gcc または clang) の場合、インスタンス化の時点でコードを追加するのは非常に簡単です。これは、カウントを保持するか、コンパイルの完了後にフィルタリングできるものをログに記録します。

Clang/LLVM の場合、インスタンス化をフックするプラグインを作成するだけで済みます。これははるかにクリーンですが、実際にはもっと多くの作業が必要になるでしょう。

デバッグ シンボルを使用し、最適化もストリッピングも行わないビルドでは、すべてのインスタンス化の名前が壊れてしまう可能性があります。ただし、一部のコンパイラ (gcc を含む) は、必要かどうかにかかわらず、常に少なくともいくつかのメソッドをインライン化します。コードを変更したい場合は、おそらく次のように、行外のインスタンス化を強制的に生成することができます。

template<int N> struct fact { 
  enum { value = N * fact<N-1>::value }; 
  int *dummy() { return &fact<N-1>::value; }
};
于 2012-07-10T00:03:52.243 に答える