0

次のコードを C++11 にバックポートしたいと思います。

template<unsigned i>
static void bar() { /* some code with compile-time optimizations for each value i */ }

template <unsigned... I>
void f()
{
  ((bar<I>()),...);
}

パラメーター パック I の各値に対する 'bar' の呼び出しの順序は重要です。fold-expression がコンマ演算子を使用しているため、上記の C++17 実装で機能していると思います。

私は最初、明示的に再帰的な実装を行いました。

template <unsigned... I>
typename std::enable_if<sizeof...(I) == 0>::type g() {}

template <unsigned head, unsigned... I>
void g()
{
  bar<head>();
  g<I...>();
}

これは機能しているように見えますが、g() には 2 つの実装が必要です。単一の関数に取り込もうとしているときに、パック展開が make_tuple で発生することを読み、これが機能すると考えました。

template<unsigned... I>
static void h1()
{
    std::make_tuple( (bar<I>(), 0)... );
}

残念ながら、これは実行順序を保証するものではありません。実際、gcc では実行順序がまったく逆になります。または、ブレース初期化リストを使用できます。

template<unsigned... I>
static void h2()
{
  using expand = int[];
  expand{ 0, ( bar<I>(), 0) ... };
}

これは gcc で順序を保持しているように見えますが、これが単なる偶然かどうかはわかりませんでした。

したがって、具体的な質問は次のとおりです。

  • h2 の実装は正しい実行順序を保証しますか?
  • 私が見逃した代替の実装はありますか?
4

1 に答える 1