Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pack expansion in variadic templates when ellipsis are on innermost element of a pattern

I saw this example on cppreference.com. I am not clear on the pack expansion of the function arguments.

Function parameter list

In a function parameter list, if an ellipsis appears in a parameter declaration (whether it names a function parameter pack (as in, Args ... args) or not) the parameter declaration is the pattern:

template<typename ...Ts> void f(Ts...) {}
f('a', 1);  // Ts... expands to void f(char, int)
f(0.1);     // Ts... expands to void f(double)

template<typename ...Ts, int... N> void g(Ts (&...)[N]) {}
int n[1];
g<const char, int>("a", n); // Ts (&...)[N] expands to const char (&)[2], int(&)[1]

Note: in this pattern, the ellipsis is the innermost element, not the last element as in all other pack expansions.

like image 607
rhlsaini Avatar asked Feb 13 '14 19:02

rhlsaini


People also ask

What is Pack expansion?

Pack expansion A pattern followed by an ellipsis, in which the name of at least one parameter pack appears at least once, is expanded into zero or more comma-separated instantiations of the pattern, where the name of the parameter pack is replaced by each of the elements from the pack, in order. template<class...

What is the use of Variadic templates?

With the variadic templates feature, you can define class or function templates that have any number (including zero) of parameters. To achieve this goal, this feature introduces a kind of parameter called parameter pack to represent a list of zero or more parameters for templates.

What is Variadic template in C++?

Variadic templates are class or function templates, that can take any variable(zero or more) number of arguments. In C++, templates can have a fixed number of parameters only that have to be specified at the time of declaration.

What is parameter pack in c++?

Parameter packs (C++11) A parameter pack can be a type of parameter for templates. Unlike previous parameters, which can only bind to a single argument, a parameter pack can pack multiple parameters into a single parameter by placing an ellipsis to the left of the parameter name.


1 Answers

This works:

template<typename ...Ts, int... N> void g(Ts (&...array)[N]) {}
int n[1];
g<const char, int>("a", n); // Ts (&...)[N] expands to const char (&)[2], int(&)[1]

but apparently many compilers have a problem if you skip the name array. I don't know if this is a quirk of the compilers or of the standard (both are reasonable: this is a serious bit of corner-case syntax).

As noted by @Xeo, a less obtuse way to deal with the declaration syntax of C is to cheat our way around the issue:

template<typename T> using Type = T;
template<typename... Ts, int... N> void g( Type<Ts[N]>&... ) {}

is easier to parse and removes the need for (at least some) compilers to have a variable name.

like image 129
Yakk - Adam Nevraumont Avatar answered Nov 15 '22 05:11

Yakk - Adam Nevraumont