ホームページ >バックエンド開発 >C++ >パック拡張を使用して C でパラメータ パックを反復するにはどうすればよいですか?

パック拡張を使用して C でパラメータ パックを反復するにはどうすればよいですか?

Mary-Kate Olsen
Mary-Kate Olsenオリジナル
2024-12-24 10:59:13463ブラウズ

How Can I Iterate Over a Parameter Pack in C   Using Pack Expansion?

可変個引数テンプレート: 反復のためのパック拡張の解明

可変個引数テンプレートは C で驚くべき表現力を与えますが、その領域に踏み込んでみると、予期せぬ複雑さが明らかになる可能性があります。このような課題の 1 つは、パック拡張を使用してパラメーター パックを反復しようとするときに発生します。次のコードを考えてみましょう:

template<typename T>
static void bar(T t) {}

template<typename... Args>
static void foo2(Args... args)
{
    (bar(args)...);
}

int main()
{
    foo2(1, 2, 3, "3");
    return 0;    
}

このコードはコンパイル時にエラー「'args': パラメータ パックはこのコンテキストで展開する必要があります。」というエラーが発生します。この問題は、関数呼び出しでパラメータ パックを直接展開できないことが原因です。

解決策は、そのような展開を明示的に許可するコンテキストである、braced-init-list 内でパック展開を利用することにあります。ダミー配列の初期化子リスト内に展開を配置することで、目的の動作を強制できます:

template<typename... Args>
static void foo2(Args &amp;&amp;... args)
{
    int dummy[] = { 0, ( (void) bar(std::forward<Args>(args)), 0) ... };
}

この改訂されたコードは、正しい評価を保証するための細心の注意を払ったアプローチを採用しています:

  • 空の展開に対するガード: 空の Args は長さ 0 の配列になります。これは、 C.これを防ぐために、配列に少なくとも 1 つの要素が含まれていることを確認します。
  • 完全転送: 潜在的なコピーを回避し、潜在的に const 修飾子を保持するために、完全転送 (std::forward) を使用します。
  • 戻り値の型を中和する: bar() の戻り値を void にキャストします組み込みのカンマ演算子を利用して、左から右への評価を保証します。

C 17 では、fold 式によりさらにコンパクトなソリューションが提供されます。

((void) bar(std::forward<Args>(args)), ...);
```

This approach guarantees the desired left-to-right expansion unequivocally.

以上がパック拡張を使用して C でパラメータ パックを反復するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。