5

コンマ演算子のチェーンであるかのように可変個引数展開を使用できないことを私は知っています。その質問では、サンプルは次のようになります。

template<typename... Args>
inline void increment_all(Args&... args) 
{
    ++args...; 
}

括弧が傷つかないように、最初にインクリメントまたは拡張するのはあいまいかもしれません。

template<typename... Args>
inline void increment_all(Args&... args)
{
    (++args)...; 
}

またはこのようなもの:

template<typename... Args>
void cout_all(Args&&... args)
{
    (std::cout << std::forward<Args>(args))...; 
}

このように、再帰トリックを使用して必要なものを取得できることを私は知っています。私が知らないのは、なぜ標準がそのような振る舞いを記述していないのかということです。つまり、その背後にある理由は何ですか?

4

1 に答える 1

5

パック展開が許可される他のコンテキストは、コンマが演算子ではなくリスト要素間の区切り文字であるリストです。

たとえばf(args...)、関数の引数リストにtuple<Args...>展開し、テンプレートの引数リストに展開します。

あなたの例では、パック展開がステートメントを形成し、ステートメントの部分式間のコンマはコンマ演算子であり、オーバーロードされる可能性があり、任意に複雑なコードにつながり、組み込みのコンマ演算子とは異なり、左から右への評価を強制しません. (std::cout << std::forward<Args>(args))...; パラメータ パック内の型の 1 つがオーバーロードされ、評価の順序が崩れたため、この例で引数が指定されていない順序で書き出された場合はoperator<<驚くoperator,でしょう。

これを行うことは、現在のルールを単純に拡張することではなく、まったく異なる効果を持つ完全に異なるコンテキストになります。

かっこが問題にならないように、最初にインクリメントするか展開するかはあいまいな場合があります。

いいえ、それはあいまいではありません。使用f(++args...)しても問題なく、明確で明確です。あなたの提案の難しさは、++args...コンマ演算子を含むステートメントに展開した後に何が起こるかを解析する方法ではありません。

于 2013-01-20T23:29:20.437 に答える