2

以下に示す定義では、G++ (4.7.2) を呼び出しqget<0>()たり使用したりできますが、「より高い」はエラーで失敗します。一方、Clang++ (3.2) は、それらのいずれでも失敗します。私は最後の手段として、怠惰なenable_if を使用しました。私はそれを必要とすべきではないと思いますが。コードが少し奇妙に見えることはわかっていますが、エラーの原因を特定できる人はいますか? (Boost は enable_if クラスを提供します。)qget<1>()qget<2>no matching function

template <typename T> struct Tid { typedef T type; };

template <unsigned I>
typename enable_if_c<(I==0),double>::type
qget()
{ return 0.0; }

template <unsigned I>
typename lazy_enable_if_c<(I!=0), Tid<decltype(qget<I-1>())>>::type
qget()
{ return qget<I-1>(); }
4

1 に答える 1

3

関数または関数テンプレートを egとして、ret foo(A, B, C);または無関心に として宣言すると、宣言されたばかりのエンティティを参照する は、いわゆる宣言子の後までスコープに含まれません。あなたの特定のケースでは、戻り値の型(遅い戻り値の型であるかどうかにかかわらず)は常に宣言子の一部です。auto foo(A, B, C) -> ret;foo

つまり、最後の宣言qgetでは、戻り値の型の名前が前の宣言を参照する可能I==0性がありますが ( の場合)、現在の宣言を参照することはありません。これがqget<0>qget<1>が見つかったのに見つからない理由qget<2>です: 後者の戻り値の型を形成しようとするとqget<1>、最初の宣言が意図したとおりに SFINAE され、2 番目の宣言が現在の宣言であり、スコープ内にないため、 が見つかりません。エラーは SFINAE になります。

これが発生した場合の私の通常の解決策 (私が言わなければならないことはそれほど頻繁ではありません) は、struct(実装の詳細として) a を使用することです。の上。

そうは言っても、 を使用しているにもかかわらず、 is の場合でも の型を ( へのパラメーターとして) 熱心に計算しているため、問題が発生する可能lazy_enable_if_c性があります。上記のタイプのアイデンティティを怠惰に評価しても、あなたは救われません。qget<I - 1>()lazy_enable_if_cI0

残念ながら、GCC 4.7.2 を使用して実行する例を取得できないようです。これは、条件を修正I > 0して遅延結果を使用する場合でも再帰を終了しないことを主張します (ただし、通常は 4.8 を使用します)。私のソリューションが機能することを約束します。

于 2012-10-03T06:19:14.430 に答える