2011-09-06 11 views
40

C++テンプレートを使用してメタプログラミングを行う場合、デバッガのような使い方があり、テンプレートがどのようにインスタンス化され、テンプレートの複雑なネットワークを作成するとき、コンパイラのエラーメッセージを見て、テンプレートがどのようにインスタンス化されているかを調べる以外に、本当に良いデバッグ方法はありません。予期せぬことが発生した場合にエラーメッセージから後ろ向きに作業しようとする試み。コンパイル時に何かを行わなければならないので、私が探しているものが存在するかどうかは分かりませんが、基本的にはコードをステップ実行してスタックフレームを調べるという方法ですgdb実行時に、コンパイラを停止して、テンプレートまたはネストされたテンプレートのセットがインスタンス化される順序について環境を調べることができます。例えばテンプレートのインスタンス化をデバッグする

は、のは、私は、次のようないくつかの簡単なコードを作成したとしましょう:

template<typename T, typename R = void> 
struct int_return_type {}; 

template<typename R> 
struct int_return_type<int, R> 
{ 
    typedef R type; 
}; 

template<typename T, typename R = void> 
struct float_return_type {}; 

template<typename R> 
struct float_return_type<float, R> 
{ 
    typedef R type; 
}; 

template<typename T> 
typename int_return_type<T>::type test() 
{ 
    cout << "T type is int" << endl; 
} 

template<typename T> 
typename float_return_type<T>::type test() 
{ 
    cout << "T type is float" << endl; 
} 

int main() 
{ 
    test<int>(); 
    test<float>(); 
    return 0; 
} 

メタプログラミングを行う場合は特に、私はこれが続くことは比較的容易なコードですけど、テンプレートはかなりより複雑に得ることができ、再帰などがあります。私は、コンパイラがテンプレートのインスタンス化方法を推測するために使用できるエラーメッセージを発行することを理解していますが、実際のテンプレートコードが構文上の意味で正しいが、結果はまだ間違っています。たとえば、testint_return_typefloat_return_typeのどちらがインスタンス化されているのか、どのインスタンシエーションが失敗したのかをコンパイラを停止する方法があるといいでしょう。

このレベルの細かさのテンプレートをデバッグするための唯一のオプションは、1)コードが正しくないときのコンパイラエラーメッセージ、2)ディスアセンブラとデバッガを組み合わせて実行時に生成されたインスタンス化されたコード時の結果が間違っていますか?あるいは、テンプレートがどのようにインスタンス化されているかを監視し、テンプレートエラーを調査してデバッグするためにコンパイラが生成するコードを見たり/調べたりするのに役立つ他のユーティリティがありますか?

+3

エラーを見たいものを作るためのstatic_assert以外何もないと思っています – Flexo

答えて

26

これらはかなり基本的なものですが、ほとんどの場合、私のために働いています。私は他の人が何を言わなければならないかを見ることに興味があります。

考案された例のお詫び。それは奇妙な行動を開始したり、複雑な何かをやっているとすぐにテストテンプレートコードに小さなサンドボックスを皮切り

使用サンドボックス

。私はかなりテンプレートに慣れていて、私はまだほとんどこれをやっています。単純に、エラーをより早く発見します。あなたはここで私たちのためにそれをしています。だから私はこれが疑問だと推測します。あなたの意図が満たされていないところ

は一時的なタイプを指定し

一時はを難読化することができます。私は以下のようなコードをたくさん見てきました。

template<typename T> 
    T calc(const T &val) { 
    return some_other_calc(val)/100.0; 
    } 

コンパイラに予期しているタイプの方が速く実行されず、より良いメッセージが表示されます。

template<typename T> 
    T calc(const T &val) { 
    T val_ = some_other_calc(val); 
    return val_/100.0; 
    } 

使用すると、デバッグ文のテンプレートの名前を印刷するtypeid(T).name()を使用し

をTYPEID。これにより、コンパイラがその型をどのように実現するかを見るために使用できる文字列が得られます。彼らが行うような方法で

template<typename T> 
    typename void test() { 
    std::cout << "testing type " << typeid(T).name() << std::endl; 
    // ... 
    } 

避け、不要なデフォルトの実装

書き込みテンプレートは、デフォルトの実装を持たない

template<typename T, bool is_integral = boost::is_numeric<T>::value > 
    struct my_traits; 

template<typename T> 
    struct my_traits<T, true> { 
    typedef uint32_t cast_type; 
    }; 

template<typename T> 
    void print_whole_number(T &val) { 
    std::cout << static_cast<my_traits<T>::cast_type>(val) << std::endl; 
    } 

これはprint_whole_numberのユーザーが独自のmy_traits専門を持って実施します。すべてのタイプに対して適切な実装を提供できなかったため、の代わりにコンパイルエラーが発生します.が機能します。コンパイラのエラーは、コードベースの異種の部分で使用された場合、すぐには役に立ちません。

+9

+1 *デフォルトの実装を持たないようにテンプレートを書く* – Manu343726

3

優れたWebベースのComeauコンパイラを使用してデバッグするのが大好きです。それは、他のコンパイラが標準コンパイルの点でエラーに気づくことがあります。

コモウは、GCCまたはMSVCよりも多くの読みやすいエラーメッセージを提供する大きな利点があります。

また、可能な限りstatic_assertを使用することを忘れないでください。答えが正しいと確信していても。

+0

これはちょっとした話題ですが、私のコードサンプルは私はそれを投稿していないでしょう(コンパイルしないコードを掲示するようなものはありません)... Comeauコンパイラのどの設定があなたでしたか?を使用して? – Jason

+0

@ Jason、C++ 0x拡張子の厳密なモード。 –

+0

@Jason、Oh stupid me、コード全体を貼り付けなかった^^ –

5

はい、テンプレートメタプログラミングデバッガがあります。 Templight

関連する問題