5

「可変引数テンプレートで参照を適切に使用する方法」を見ていて、カンマ展開がどこまでできるのか疑問に思いました。

答えの変形は次のとおりです。

inline void inc() { }

template<typename T,typename ...Args>
inline void inc(T& t, Args& ...args) { ++t; inc(args...); }

可変個引数は要素のコンマ区切りリストに展開されるため、これらのコンマは意味的にテンプレート/関数引数セパレータと同等であるか、語彙的に挿入され、コンマ演算子を含む任意の (ポストプリプロセッサ) 使用に適しています。 ?

これは私の GCC-4.6 で動作します:

// Use the same zero-argument "inc"

template<typename T,typename ...Args>
inline void inc(T& t, Args& ...args) { ++t, inc(args...); }

しかし、私が試したとき:

// Use the same zero-argument "inc"

template<typename T,typename ...Args>
inline void inc(T& t, Args& ...args) { ++t, ++args...; }

「;」を期待して、解析エラーが発生し続けました。「...」の前にあり、その「args」はそのパックを展開しません。うまくいかないのはなぜですか?「args」が空の場合、句読点の無効な塊が得られるためですか? それは合法ですか、私のコンパイラは十分ではありませんか?

(「引数」を括弧で囲んだり、ポストインクリメントを使用したりしましたが、どちらも機能しませんでした。)

4

1 に答える 1

6

アンパックは特定のコンテキストでのみ許可され、カンマ区切りのステートメントはそれらに属しません。言葉の使い方: 展開は意味論的であり、語彙的ではありません。ただし、他にもいくつかの方法があるため、それは問題ではありません。単純な可変個引数関数を記述するためのある種のパターン/イディオムが既にあります。それを行う1つの方法:

何もしないヘルパー テンプレート関数を使用します。

template <typename ...Args>
void pass(Args&&...) { }

コンマ演算子を使用する代わりに、式をこの関数に渡します。

template <typename ...Args>
void inc(Args&&... args)
{
    pass(++std::forward<Args>(args)...);
}

式をより複雑にする必要がある場合は、展開内でコンマ演算子を使用できます。operator++戻り値の型がいくつかある場合、これはあなたの場合に役立つかもしれませんvoid:

    pass((++std::forward<Args>(args), 0)...);
于 2012-04-19T11:06:45.927 に答える