次のコードを 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 の実装は正しい実行順序を保証しますか?
- 私が見逃した代替の実装はありますか?