1. ホーム
  2. c++

[解決済み] Variadicテンプレートパック拡張

2023-04-13 07:47:44

質問

私は変種テンプレートと関数を学ぼうとしています。私はなぜこのコードがコンパイルされないのかを理解することができません。

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;    
}

コンパイルするとエラーで失敗します。

エラー C3520: 'args': パラメータパックはこのコンテキストで展開する必要があります。

(関数 foo2 ).

どのように解決するのですか?

パックの膨張が発生する場所の1つに braced-init-list . ダミー配列のイニシャライザーリストの中に展開を入れることで、この利点を利用することができます。

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

イニシャライザの内容をより詳しく説明するため。

{ 0, ( (void) bar(std::forward<Args>(args)), 0) ... };
  |       |       |                        |     |
  |       |       |                        |     --- pack expand the whole thing 
  |       |       |                        |   
  |       |       --perfect forwarding     --- comma operator
  |       |
  |       -- cast to void to ensure that regardless of bar()'s return type
  |          the built-in comma operator is used rather than an overloaded one
  |
  ---ensure that the array has at least one element so that we don't try to make an
     illegal 0-length array when args is empty

デモ .

で展開することの重要な利点は {} で展開することの重要な利点は、左から右への評価が保証されることです。


C++17で 折りたたみ式 と書くだけでよい。

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