3

テンプレートメタプログラミングでは、再帰が誤って実装され、結果として無限ループが発生した場合、言語コンパイラはそれを検出できますか?それとも、コンパイラは最終的にスタックオーバーフローに遭遇してクラッシュするのでしょうか?私の考えでは、コンパイラーはこれを検出できないでしょう。なぜなら、そうすることは停止性問題の決定不可能性に違反するからです。

私は結論で正しいですか?もちろん、これをコードで試すこともできますが、この場合は、より適切な考え方を聞きたいと思います。

編集:みんなありがとう、私はtmpの計算理論の側面に関する私の推論が間違っていなかったという一般的な考えを得る。また、コンパイラの実装には任意の再帰深度制限がある可能性があることも理解しています(もちろん、この2番目の部分をテストできたことを繰り返しますが、それは私の副次的な点にすぎません)。

4

6 に答える 6

3

一般に、このような無限の再帰を検出することはできません。テンプレートメタプログラミングはTuringに対応しており、そのような検出は停止性問題の解決に相当します。Turingの難しい問題でよくあることですが、それは特定のケースを検出できないという意味ではありません。

コンパイラーは、テンプレートが標準によってネストできる最小数のレベルと、ネストが深すぎると診断する最大数のレベルを持っている傾向があると思います。

于 2012-06-03T19:22:40.280 に答える
2

この規格では、実装によって、次のような数量を制限できる(そして効果的に制限する)と規定されています。

附属書B

  • テンプレート引数の推論中の置換を含む、再帰的にネストされたテンプレートのインスタンス化(14.8.2)

コンパイラは、この量の事前定義された制限に達すると、適切なエラーメッセージとともに、おそらくベイルアウトします。

于 2012-06-03T19:26:13.180 に答える
1

テンプレートメタプログラミングはチューリング完全であるため、はい、すべての場合に無限ループを検出できるコンパイラであれば(終了ループを誤って無限として分類することなく)、停止の問題を解決できます。

ただし、通常のコードと同様に、いくつかの無限ループが検出される可能性があります。ただし、コンパイラがチェックすることはないと思います。代わりに、最大再帰深度を超えると文句を言うだけです。

于 2012-06-03T19:22:11.280 に答える
1

はい、通常は検出可能です

一般的なケースでは停止問題は決定不可能ですが、最も具体的なケースではないにしても、多くの場合は確かに決定可能です。

そして、それを行うための簡単で明白な方法:許可される再帰の量を制限します。

したがって、一般的に、答えは最初です。無限ループを検出します

(特定の場合に間違っていることを受け入れることができれば、停止しないプログラムを簡単に検出できます。結局のところ、無制限の再帰はどのコンパイラーでも許可されていません。)

于 2012-06-03T19:33:50.957 に答える
0

あなたは正しいです。テンプレートメタプログラミングで再帰スタックフレームを制限せずに無限再帰を検出することは、停止問題の代替ソリューションを見つけることを意味します。

理論的には検出可能ないくつかの特殊なケースがあります。たとえば、再帰の参照透過性を確保でき、最後の関数呼び出しが実際のパラメーターと同じパラメーターを受け取った場合、無限再帰呼び出しになります。C ++は、テンプレートメタプログラミングに関する参照透過性の保証を提供していません。

于 2012-06-03T19:33:58.123 に答える
0

もちろん、参照透過性のために無限ループを検出することは可能です。それは些細なことですが、どのコンパイラがそれを行うかはテストしていません。

一方、再帰が無限の異なるテンプレートのインスタンス化(インスタンス化レベルでループしない)を生成する場合、検出することはほとんどまたは不可能です。これはTurungの完全性によるものです。

テンプレートのインスタンス化ごとに、コンパイラはすべてのノードがテンプレートのインスタンス化である有限ツリーグラフを生成します。コンパイラがバックエッジを検出するとすぐに/ループのためにグラフがツリーではないことを検出すると、コンパイラは中止する必要があります。無限のグラフ/ツリー(停止問題)は、おそらくタイムアウト/制限されたグラフサイズで検出されます。

于 2012-06-03T19:47:34.037 に答える