C 14 では、integer_sequence クラス テンプレートの作成を簡素化するために、make_integer_sequence エイリアス テンプレートが導入されました。 make_integer_sequence を実装するには、ヘルパー構造体 make_helper が使用されます。
template< class T, T... I> struct integer_sequence { typedef T value_type; static constexpr size_t size() noexcept { return sizeof...(I) ; } }; template< class T, T N> using make_integer_sequence = integer_sequence< T, 0,1,2, ... ,N-1 >; // only for illustration.
ここで問題が発生します。実装では、make_helper 構造体は再帰的アプローチを使用します。これは簡単な解決策のように思えるかもしれませんが、特に N パラメータが大きい場合、テンプレートのインスタンス化が急速に増加する可能性があります。
template< class T, T N, T... I > struct make_helper { typedef typename mpl::if_< T(0) == N, mpl::identity< integer_sequence<T,I...> >, make_helper< T, N-1, N-1,I...> >::type; };
この急激な増加により、コンパイラは仮想メモリをすぐに使い果たす可能性があります。 GEN マクロを変更して 4 の倍数の整数シーケンスを生成したときに発生したように、
メモリ枯渇の問題は、対数深さの実装を採用することで解決できます。このアプローチにより、再帰呼び出しの数が最小限に抑えられ、テンプレートのインスタンス化の深さが減ります。
template<unsigned...> struct seq{ using type = seq; }; template<class S1, class S2> struct concat; template<unsigned... I1, unsigned... I2> struct concat<seq<I1...>, seq<I2...>> : seq<I1..., (sizeof...(I1)+I2)...>{}; template<class S1, class S2> using Concat = Invoke<concat<S1, S2>>; template<unsigned N> struct gen_seq; template<unsigned N> using GenSeq = Invoke<gen_seq<N>>; template<unsigned N> struct gen_seq : Concat<GenSeq<N/2>, GenSeq<N - N/2>>{}; template<> struct gen_seq<0> : seq<>{}; template<> struct gen_seq<1> : seq<0>{};
この対数的な深さの実装では、再帰の深さは N とともに対数的に増加します。これにより、メモリ消費が大幅に削減され、次のコンパイルが可能になります。 N の値がはるかに大きい整数シーケンス。
対数深さの実装を採用することで、仮想メモリの枯渇という元の問題が解決されます。 N の大きな値を持つ整数シーケンスの生成を可能にします。
以上がメモリの枯渇を避けるために C 14 の `make_integer_sequence` 実装を最適化するにはどうすればよいでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。