Contexts in which pack expansions can occur - c++

There is a clear and comprehensible list of contexts in which a pack expansion can occur on cppreference.com. What I am trying to do is to derive the same information from the standard, partly to gain experience in using the standard. However, I am unable to derive all pack expansion contexts listed on cppreference.com from the standard.
cppreference.com lists, among others, the following four contexts: function argument lists, template argument lists, function parameter lists and template parameter lists.
On the other hand, the standard says (14.5.3.4):
A pack expansion consists of a pattern and an ellipsis, the instantiation of which produces zero or more instantiations of the pattern in a list (described below). The form of the pattern depends on the context in which the expansion occurs. Pack expansions can occur in the following contexts:
In a function parameter pack (8.3.5); the pattern is the parameter-declaration without the ellipsis.
In a template parameter pack that is a pack expansion (14.1):
if the template parameter pack is a parameter-declaration; the pattern is the parameter-declaration without the ellipsis;
if the template parameter pack is a type-parameter with a template-parameter-list; the pattern is the corresponding type-parameter without the ellipsis.
...
In a template-argument-list (14.3); the pattern is a template-argument.
...
I am unable to find out where the standard says that pack expansion can occur in function argument lists. I suppose this context is somehow covered by one of the three bullet points quoted above.
Just in case it is unclear what I mean by pack expansions in function argument lists, consider the following example:
template <typename ...Args> void f(Args ...args) {}
template <typename ...Args> void g(Args ...args) {
f(args...); // Pack expansion in a function argument list.
}

A function argument list is syntactically an initializer-list1, so it's covered by [temp.variadic]/(4.4):
In an initializer-list; the pattern is an initializer-clause.
1. The grammar of a function call is postfix-expression ( expression-listopt ). And an expression-list is just an initializer-list. ([expr.post])

Related

What does it mean that function parameter packs are always pack expansions, so their declared types must include at least one parameter pack?

In this snippet
template<typename... Types>
void f(Types ... args);
Types is the template parameter pack and args is a function parameter pack.
Concerning the two technical terms, C++ Templates - The Complete Guide 2nd Edition reads
Unlike template parameter packs, function parameter packs are always pack expansions, so their declared types must include at least one parameter pack.
What does that mean? What is the example of non-at least one, i.e. zero in the context of that sentence?
It says that a function parameter pack can only be created using another parameter pack, rather than from scratch.
What is the example of non-at least one, i.e. zero in the context of that sentence?
E.g. int ...params is illegal, because it doesn't contain any existing packs.

The wording about instantiation of a pack expansion in [temp.variadic]

I wonder Is it a mis-wording in the following quote, that is
temp.variadic#7
The instantiation of a pack expansion that is neither a sizeof... expression nor a fold-expression produces a list E1,E2,...En
, where N is the number of elements in the pack expansion parameters. Each Ei is generated by instantiating the pattern and replacing each pack expansion parameter with its ith element. Such an element, in the context of the instantiation, is interpreted as follows:
if the pack is a template parameter pack, the element is a template parameter of the corresponding kind (type or non-type) designating the type or value from the template argument; otherwise,
if the pack is a function parameter pack, the element is an id-expression designating the function parameter that resulted from the instantiation of the pattern where the pack is declared.
The pattern of a function parameter pack is a parameter-declaration without ellipsis because it's defined as the following:
temp.variadic#4
A pack expansion consists of a pattern and an ellipsis, the instantiation of which produces zero or more instantiations of the pattern in a list (described below). The form of the pattern depends on the context in which the expansion occurs. Pack expansions can occur in the following contexts:
[...]
In a function parameter pack ([dcl.fct]); the pattern is the parameter-declaration without the ellipsis.
A usual parameter-declaration consists of :
attribute-specifier-seq (opt) decl-specifier-seq declarator
attribute-specifier-seq (opt) decl-specifier-seq declarator = initializer-clause
attribute-specifier-seq (opt) decl-specifier-seq abstract-declarator(opt)
attribute-specifier-seq (opt) decl-specifier-seq abstract-declarator (opt) = initializer-clause
In any case , the decl-specifier-seq is not an optional component.
In this example
template<typename...T>
void func(T...args){
}
T...args is a function parameter pack, thereof, T args is its pattern. So my issues is, why the element generated from instantiation of a pattern of a function parameter pack is id-expression, However the id-expression is only a part of declarator of a parameter-declaration.
I try to answer this question, To understand these sentences, These sentences are necessary to split to several portions.
A function parameter pack is a function parameter that accepts zero or more function arguments.
What is a function parameter pack?
In c++17 standard, it says:
dcl.fct#16
A declarator-id or abstract-declarator containing an ellipsis shall only be used in a parameter-declaration. Such a parameter-declaration is a parameter pack. When it is part of a parameter-declaration-clause, the parameter pack is a function parameter pack.
It sounds like a parameter-declaration where declarator-id or abstract-declarator containing an ellipsis and such a parameter-declaration appears in parameter-declaration-clause, such a parameter-declaration is a function parameter pack. Right?
Now, we see what the latest draft says:
dcl.fct#21
A declarator-id or abstract-declarator containing an ellipsis shall only be used in a parameter-declaration. When it is part of a parameter-declaration-clause, the parameter-declaration declares a function parameter pack.
It says a parameter-declaration where declarator-id or abstract-declarator containing an ellipsis and such a parameter-declaration appears in parameter-declaration-clause, as far as here, they are the same, however, the difference is here, such parameter-declaration declares a function parameter pack. It means T...args declares a function parameter pack.
A pack expansion consists of a pattern and an ellipsis, the instantiation of which produces zero or more instantiations of the pattern in a list... Pack expansions can occur in the following contexts:
In a function parameter pack ([dcl.fct]); the pattern is the parameter-declaration without the ellipsis.
The sentence means a pack expansion occurred in a context that is a function parameter pack, the pattern is the parameter-declaration without the ellipsis. Informally, for this case T...args, thereof T... denotes a pack expansion and the pattern of T...args is T args.
The instantiation of a pack expansion...
if the pack is a function parameter pack, the element is an id-expression designating the function parameter that resulted from the instantiation of the pattern where the pack is declared.
About the third bullet, this pack doesn't denote T, it is a stuff declared by a parameter-declaration as the analysis of the first bullet. Another important point to understand this sentence is function parameter that resulted from the instantiation of the pattern where the pack is declared, As the aforementioned, the pattern is T args where the pack is declared. So, the emphasized sentence means function parameter is the result from these instantiations of pattern T args of pack expansion T...args, Now it confirms to the second bullet, and for some case like postfix-expression(args...), The pack args is used to be a pattern of such pack expansion and the instantiation of such pack expansion would be the id-expression designating the function parameter which from the instantiation of the pattern T args.
In that pack expansion, T and args are expanded (even as the latter is being declared as a pack); as such, the resulting parameter-declarations have the form T1 args1,T2 args2,… and are properly equipped with a decl-specifier.

What kind of type-specifier within decl-specifier-seq grammar tree can denote the type-specifier when it's a template parameter pack

template<typename...T>
void func(T...){
}
Consider the above code , it's a case what the standard mentioned:
There is a syntactic ambiguity when an ellipsis occurs at the end of a parameter-declaration-clause without a preceding comma. In this case, the ellipsis is parsed as part of the abstract-declarator if the type of the parameter either names a template parameter pack that has not been expanded or contains auto; otherwise, it is parsed as part of the parameter-declaration-clause.
So, the parameter-declaration is the form of the following:
dcl.fct#3
parameter-declaration:
attribute-specifier-seq(opt) decl-specifier-seq abstract-declarator(opt)
Thereof, the abstract-declarator denotes ..., However, I couldn't find a type-specifer within decl-specifier-seq's grammar tree can denote T.
dcl.spec#1
decl-specifier:
storage-class-specifier
defining-type-specifier
function-specifier
friend
typedef
constexpr
inline
decl-specifier-seq:
decl-specifier attribute-specifier-seq (opt)
decl-specifier decl-specifier-seq
Because T here is an unexpanded template parameter type. So T is not typedef-name, because of this:
temp.param#3
A type-parameter whose identifier does not follow an ellipsis defines its identifier to be a typedef-name (if declared without template) or template-name (if declared with template) in the scope of the template declaration. [ Note: A template argument may be a class template or alias template.
So, I wonder what something within the decl-specifier-seq grammar tree can denote the template parameter pack T which has not been expanded? As far as now, I have not found a type-specifier associated with T. If I miss anything, Please correct me.
UPDATE
For this question, I'm digging in the further into temp.variadic#5 section, and I found something that says:
For the purpose of determining whether a parameter pack satisfies a rule regarding entities other than parameter packs, the parameter pack is considered to be the entity that would result from an instantiation of the pattern in which it appears.
My reading about this sentence is, the parameter pack is required to satisfy the rule about a parameter-declaration, hence when invoke the function like func(0,0.1), the instantiation of the pattern of the pack expansion are int,double, respectively, due to:
temp.variadic#4
A pack expansion consists of a pattern and an ellipsis, the instantiation of which produces zero or more instantiations of the pattern in a list (described below)
In a function parameter pack ([dcl.fct]); the pattern is the parameter-declaration without the ellipsis.
So, the results from these instantiations are used to be the type-specifier. It means int,double will be the type-specifier for these parameter-declarations of this case func(0,0.1), However it's my reading, I'm not sure it is a relevant rule for this questions.
And it will result in another question, for template<typename...T> void func(T...);, the parameter pack is not a function parameter pack, due to this rule:
A declarator-id or abstract-declarator containing an ellipsis shall only be used in a parameter-declaration. Such a parameter-declaration is a parameter pack. When it is part of a parameter-declaration-clause, the parameter pack is a function parameter pack. [ Note: Otherwise, the parameter-declaration is part of a template-parameter-list and the parameter pack is a template parameter pack; see [temp.param].  — end note ]
In my question, the parameter pack is parsed as a part of the abstract-declarator, not the part of a parameter-declaration-clause because the first quote said that. hence, the parameter pack is not considered to be a function parameter pack at all? Now, I think this question has became more complex. I'm looking forward to an answers for this question.

What is the word pack in C++ draft?

What is the pack means in the C++ draft standard [basic]p3? Could you provide some concrete explanation, if cannot be explained in precise term?
An entity is a value, object, reference, structured binding, function, enumerator, type, class member, bit-field, template, template specialization, namespace, or pack.
The standard also has an index and if we search for pack in the index we have the following entry for pack:
pack, [temp.variadic]
which leads to [temp.variadic]p4 which says:
A pack is a template parameter pack, a function parameter pack, or an init-capture pack.
The number of elements of a template parameter pack or a function parameter pack is the number of arguments provided for the parameter pack.
The number of elements of an init-capture pack is the number of elements in the pack expansion of its initializer.

Seemingly defective paragraph regarding template argument deduction?

Omitting a template argument is possible, since the standard says in 17.9.1, paragraph 3 [temp.arg.explicit] (N4700):
Trailing template arguments that can be deduced or obtained from default template-arguments may be omitted from the list of explicit template-arguments...
On the other hand, the standard has a conflicting rule, as 17.9.2, paragraph 2 [temp.deduct] shows (emphasis mine):
... Specifically, the following steps are performed when evaluating an explicitly specified template argument list with respect to a given function template:
If the specified template arguments do not match the template parameters in kind (i.e., type, non-type, template), or if there are more arguments than there are parameters and no parameter is a template parameter pack, or if there is not an argument for each non-pack parameter, type deduction fails.
...
This paragraph suggests that all template arguments shall be specified if we were to use a explicit template argument list, which clearly contradicts to the above paragraph. Then, what's the intention?
The second quote applies "when evaluating an explicitly specified template argument list", but the first clearly is about the case when some template arguments are not explicitly specified. There's no conflict, because they're talking about two different situations.