C ++はどのように継続的な通過スタイルを使用できますか?

C ++で、再帰関数に対して多すぎる再帰呼び出しを行い、スタックオーバーフローエラーが発生したとします。

スタックのオーバーフローを避けるために、これを継続渡しスタイルでどのように書き直しますか?

私はこれをC ++でやや難解にしています。

9
そのような抽象的な質問のための抽象的な答え以外は何も得られません。たぶんスタックオーバーフローの原因となっている関数の例を投稿して、それを修正する方法について具体的な回答を得られるはずです。 (個人的には、アキュムレータを使用して継続を使用するように書き換える前に関数を書き直そうとします...)
追加された 著者 ildjarn,
@ highwind7777:どんな抽象的な答えを期待していますか? "ステートフルファンクタを使用する"?コンパイラがTCOをサポートしている限り、アキュムレータの使用に関しては、再帰を続けることはできません。
追加された 著者 ildjarn,
あなたは正しい場所に来ました。
追加された 著者 Eddy Pronk,
@ildjarn、通知のおかげで。私は抽象的な答えを実際に探しています。アキュムレータを使用すると、C ++の通常の反復処理として書き直すことはできませんか?
追加された 著者 achow,

1 答え

まあ、それはむしろオープンな質問ですが、Eric Lippertは実際には長いシリーズをご覧ください。必ずしも正しい言語ではありませんが、それはまだまだ役立ち、一般的な考え方を与えるべきです。

C ++でCPSを実装することは、単一の再帰関数を修正するだけの多くの作業のようですが、キューを使って関数を繰り返し実行するアルゴリズムを使うことができます(ただし、基本的に同じ量のデータを使用しますが、制限が少ない)。

4
追加された
@EricLippertあなたは正しく、私はC ++ 11ラムダを想定していましたが、明らかにラムダをサポートするコンパイラを持っているのは誰も(大多数には至っていません)。それがなければ、はるかに複雑になります(クラスを使用し、おそらく周りのものを渡しますか?)。 Btwあなたの素晴らしい記事をありがとう - あなたなしで私はCPSが何であるか知りません:)
追加された 著者 Voo,
@ highwind7777関数ポインタは、クロージャを実装したい場合にはあまり役に立ちません。どのようにしてそれをやっているのか分かりませんが、実行可能コードへのポインタだけではなく、どこかにストレージが必要です。
追加された 著者 Voo,
@Voo:C ++ 11ラムダがなくても、これを扱うC ++ 03ライブラリがあります。例えば、 Boost.Phoenix
追加された 著者 ildjarn,
私は、組み込みの言語機能として字句クロージャを持つ言語の文脈で、これらのシリーズを両方書くという明確な利点がありました。 C ++コードをクロージャーに書き直すことはもちろん完全に達成可能ですが、それは少し苦しいでしょう。
追加された 著者 Eric Lippert,
@ highwind7777:あなたがそれをやり遂げる方法はいくつかあります。自動ガベージコレクションの欠如のために、この問題はC ++では非常に複雑です。閉鎖の生涯が正確に何であるかを知ることは難しいかもしれません。私は決してそのようなことをしようとはしていないし、決してしなければならないことを願っています!
追加された 著者 Eric Lippert,
リンクありがとう。 @EricLippert C ++コードをクロージャに書き直すことで、コールチェーンを渡すことによって、閉じた(境界のある)変数を手動で維持することを意味しますか?
追加された 著者 achow,
@Voo、私はそれがJavaスタイルのやり方であると思う。 C ++では、関数ポインタを利用してより洗練されたクロージャの実装を得ることができます。
追加された 著者 achow,