Search code examples
c++c++14variadic-templatesvariadic-functions

Parameter packs not expanded with '...'


I have this code:

#include <iostream>
using namespace std;

int print(int i)
{
    cout << endl << i;
}

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

}

template<typename ...args>
inline void expand(args&&... a)
{
    print(a) ...; //this doesn't expand
    //pass( print(a)... ); this works
}

int main() {
    expand(1,2,3,4);
    return 0;
}

It throws an error:

 In function 'void expand(args&& ...)':
error: expected ';' before '...' token
  print(a) ...;
           ^
parameter packs not expanded with '...':
  print(a) ...;
              ^

Why is the use of the pass() function necessary?


Solution

  • Essentially, expanding a parameter pack E... produces a list E1, E2, [...], EN, one E for each element in the pack. This syntactic construct is only valid in places where lists are grammatically correct, such as in function calls, initializer lists etc. An expression containing multiple comma operators does not count.

    I believe that with fold expressions (N4295: Folding expressions (Andrew Sutton, Richard Smith)) you'll be able to simply write:

    (print(a), ...);
    

    In this expression,

    • print(a) is an expression with an unexpanded parameter pack,
    • , is the operator and
    • ... designates the right fold expansion.

    The result of the entire expression is that (print(a), ...) will be transformed into

    print(a1) , (print(a2), (print(a3), print(a4))) // (assuming four elements).