2017-02-03 7 views
1

は、ここに私の簡略化されたテストコードです:私はGCCと打ち鳴らすと、このコードをコンパイルすると無限テンプレートのインスタンス

struct Test { 
    Test() { run(0); } 

    template<class T> 
    static auto run(T&&, bool stop = false) -> void { if (!stop) _run<T>(); } 
    template<class R> 
    static auto _run() -> void { []() { run([]() {}, true); }(); } 
}; 

、それはコンパイルエラーを与える:

/media/data/caca3d/src/b0util/test/tst_promise.cpp:30: error: template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum) 
static auto _run() -> void { []() { run([]() {}, true); }(); } 
             ~~~^~~~~~~~~~~~~~~~ 

私は、なぜこのコードの原因を見ることができません無限のテンプレートインスタンス化。

template<class R>_run()の機能を削除した場合、エラーはなくなりました。

ラムダ関数で遅延評価を試したときにこのエラーが見つかったため、ラムダの間接呼び出しを削除できません。 この問題を解決するにはどうすればよいですか?

+0

最初にテンプレートとして使用するには、実際に_runが必要ですか? – SingerOfTheFall

+0

はい。このコードはテストのために単純化されています。実際のコードは、テンプレートとテンプレートのメタプログラミングを大きく利用しています。 – xylosper

+0

OK、MCVEを作成してくれてありがとう=) – SingerOfTheFall

答えて

1

何が起こっているかを詳しく見てみましょう。最初の関数は明示的に_run()のテンプレートバージョンを呼び出しますが、あなたはこの部分に疑問がないと思います。

template<class T> 
static auto run(T&&, bool stop = false) -> void { if (!stop) _run<T>(); } 

2番目の方が面白いです。 (run()をラムダで1回呼び出すだけなので)一度インスタンス化されるように見えるかもしれませんが、各ラムダは独自の固有の型を持っていますので、_run()がインスタンス化されるたびにrun()の新しいバージョン(関数の引数型からTが導き出されるため)は無限ループになります。

template<class R> 
static auto _run() -> void { []() { run([]() {}, true); }(); } 

run()を作ることになり、この特定の例では、この問題を解決する最も簡単な方法は、特定のstd::function取る(多分テンプレートパラメータ依存)それはあなたのラムダと一致して入力します。

+0

ありがとうございました。たぶん、ラムダの代わりに有限のインスタンス化された型を持つstd :: functionを使用しようとします。どうもありがとう。 – xylosper

+0

@xylosper、そうですね、それはまさに私が提案しようとしていたものです)= – SingerOfTheFall

+0

@xylosper、ところで(あなたが実際にそれを必要とするかどうかはわかりませんが、素晴らしい機能です)、 'std :: function'引数の型パックに基づいています。たとえば、 'template のような引数パックに基づいています。ArgumentTypes> class function_wrapper {public:std :: function functionPointer}; ' – SingerOfTheFall

関連する問題