10

私は C++17の折り畳み式を調べていますが、なぜ次のプログラムが出力されるのか疑問に思っています。

4 5 6 
4 5 6 

両方のfor_each呼び出しに対して

template<typename F, typename... T>
void for_each1(F fun, T&&... args)
{
    (fun (std::forward<T>(args)), ...);
}

template<typename F, typename... T>
void for_each2(F fun, T&&... args)
{
    (..., fun (std::forward<T>(args)));
}

int main()
{
     for_each1([](auto i) { std::cout << i << std::endl; }, 4, 5, 6);
     std::cout << "-" << std::endl;
     for_each2([](auto i) { std::cout << i << std::endl; }, 4, 5, 6);
}

Live Example

2番目のfold式は数値を逆順に出力するためのものだと思っていました

6 5 4

結果が同じなのはなぜですか?

4

1 に答える 1

10

§ 14.5.3/9 によると

fold-expression のインスタンス化により、以下が生成されます。

(9.1) — ((E1 op E2) op · · · ) op EN 単項左折畳、

(9.2) — E1 op (··· op (EN-1 op EN ))単項右折畳、

(9.3) — (((E op E1) op E2) op · · · ) op EN バイナリ左フォールドの場合、および

(9.4) — E1 op (··· op (EN-1 op (EN op E))) バイナリ右折畳

いずれの場合も、op はフォールド演算子、N はパック展開パラメーターの要素数です。各 Ei は、パターンをインスタンス化し、各パック展開パラメーターをその i 番目の要素に置き換えることによって生成されます。

上記のコードでは、それらは両方とも単項折り畳み式であり、それらの展開は

template<typename F, typename... T>
void for_each1(F fun, T&&... args) {

    // Unary right fold (fun(args_0) , (fun(args_1) , (fun(args_2) , ...)))
    (fun (std::forward<T>(args)), ...);
}

template<typename F, typename... T>
void for_each2(F fun, T&&... args) {

    // Unary left fold ((fun(args_0) , fun(args_1)) , fun(args_2)) , ...
    (..., fun (std::forward<T>(args))); 
}

そのため、式はコンマ演算子で定義されたものと同じ評価順序を持ち、したがって出力は同じです。

クレジット:最初に元の質問を提起し、誤解を招く可能性があるこの問題を解決する機会を与えてくれた友人のMarcoに感謝します。

于 2015-06-13T14:07:49.790 に答える