私はそれをよりよく理解するために、いくつかのテンプレートコードをデバッグしたいと思います。
は、残念ながら私はテンプレートメタプログラミングに新たなんだと私はに取得することが困難であるC++テンプレートメタプログラミング - 生成されたコードを出力することは可能ですか?
私が出力する前処理ソースファイルをしようとすると、私はコードの125 000行を取得します:/
がそうであるが私は生成されたコードを見ることができますか? (私が使っているライブラリはSeqAnです)
私はそれをよりよく理解するために、いくつかのテンプレートコードをデバッグしたいと思います。
は、残念ながら私はテンプレートメタプログラミングに新たなんだと私はに取得することが困難であるC++テンプレートメタプログラミング - 生成されたコードを出力することは可能ですか?
私が出力する前処理ソースファイルをしようとすると、私はコードの125 000行を取得します:/
がそうであるが私は生成されたコードを見ることができますか? (私が使っているライブラリはSeqAnです)
いいえ、それはありません。プリプロセッサは、コンパイラによって実行されるテンプレート処理とは何の関係もありません。テンプレートはC++コードを生成しません。関数呼び出し以外にも、C++言語自体の不可欠な部分です。
これは一般的には真実ですが、プリプロセッサでも理論的には真です。実際には、最も簡単な実装は、プリプロセッサステージの出力としてC++のようなコードを生成することですが、テンプレートのインスタンス化では生成しません。その逆は不当に困難ですが、技術的に不可能ではありません。主な問題は名前の検索であり、コンパイラはテンプレートのインスタンス化中に一意の名前を生成する可能性があります。 – MSalters
正に言っても、インスタンス化すると、デバッガを使用して計算されたタイプを表示することができます。私は、Visual C++を使用する方法の例を作りました。私はメタプログラムのために非常に頻繁に使用しました。 – ovanes
これは潜在的にあなたの質問への答えです:
C++ Template preprocessor tool
は尋ねた最後の人満足しているようだ - 私はなぜ想像できないにもかかわらずを! C言語でのC++コンパイラの出力は、理解の助けになるものではなく、単に移植可能なアセンブリ言語の一種であるため、通常はかなり読めません。
一般に、コード全体を出力することはできません。しかし、私が非常に面白いと分かったのは、Visual C++デバッガを使用してそのタイプを表示できることです。その単純なメタプログラムを取ってください:
template<class Head, class Tail>
struct type_list
{
typedef Head head;
typedef Tail tail;
};
struct null_type
{};
template<class List>
struct list_head
{
typedef typename List::head head;
};
template<class List>
struct list_tail
{
typedef typename List::tail tail;
};
template<class List>
struct list_length
{
static const size_t length = 1+list_length< typename list_tail<List>::tail >::length;
};
template<>
struct list_length<null_type>
{
static const size_t length = 0;
};
int main()
{
typedef
type_list
< int
, type_list
< double
, type_list
< char
, null_type
>
>
> my_types;
my_types test1;
size_t length=list_length<my_types>::length;
list_head<list_tail<list_tail<my_types>::tail>::tail>::head test2;
}
私はちょうど私のメタタイプをインスタンス化しました。これらは少なくとも1バイト長の空のC++クラスインスタンスです。今、私は長さ、TEST1とTEST2がのである種類/値、TEST2の最後のインスタンス化の後にブレークポイントを入れて見ることができます:ここで
デバッガが示しものです:
length 3 unsigned int
test1 {...} type_list<int,type_list<double,type_list<char,null_type> > >
test2 -52 'Ì' char
今あなたが知っています頭部はあなたにキャラクターを返しました、あなたのリストはint、double、charを含み、null_typeで終わります。
これは私を大きく助けました。時には、本当に面倒な型をテキストエディタにコピーし、それを読みやすい形式に整形する必要があるかもしれませんが、内部のものと計算方法をトレースする可能性があります。
、
Ovanes
を役に立てば幸いいや、一般的に、それは行うことはできません。テンプレートは単にC++言語の一部であり、別々のプリプロセッサではないため、C++コードを生成しません。
通常の解決策は、正しいテンプレートが適切な方法でインスタンス化されることを検証するために、静的なアサートおよびその他のテストでコードを振りかけることです。
あなたのメタプログラミングで迷子に開始すると、この単純なトリックを使用すると、テンプレートパラメータが実際にどのタイプかを決定することができます:
// given a variable t of an unknown type T
int*** i = t;
コンパイラはこれを検出すると、それがいいとシンプルをプリントアウトします"<long, detailed typename>
をint ***に変換できません"というエラーメッセージが表示され、テンプレートパラメータTが実際に必要と思われるタイプであることを簡単に確認できます。あなたはそれがどのように動作するかを見ることができ、6ページから
チェックmy publication on C++ template metaprogram debugging
。特定の目的のためには、ツールチェーン全体を必要とせず、手作業で行うことができます。
私はブレークポイントなどを置くことができるVisual C++アドインをまとめましたが、それは毎日の使用のためのツールよりもむしろ概念の証明でした。
私たちはすべてのインスタンス化を表示し、デバッグとプロファイリングを可能にするグラフィカルフロントエンドに取り組んでいます。残念ながら、私たちは非常に限られたフリータイムでそれを行うので、そのツールの公開日を約束することはできません。
UPDATE:デバッガとプロファイラがhere
UPDATE提供されています:C++Now presentation
面白そうですね! –
ありませんが、それはする必要があります。誰かがClangプロジェクトとしてこれを行うべきです:D –
[SFINAE](https://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error)のために、各テンプレートをハードコードされた代替ファイルおそらく違法であろう。例えば。呼び出されない限り、テンプレートクラスのメソッドは存在しないものを呼び出すことがあります。 – MvG
@JosephGarvinここにはClangベースのプロジェクトがあります。最新の[Templight、clangベースのテンプレートインスタンス化プロファイラとデバッガ](https://github.com/mikael-s-persson/templight)、[Templar visualizer](https://github.com/) schulmar/Templar)、[Metashell](https://github.com/sabel83/metashell)などがあります。 –