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

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.

Related

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.

Deduction failure of function call with explicit template argument list and [temp.arg.explicit]/3

[temp.arg.explicit]/3 of the C++17 standard (final draft) says about deduction of function template arguments with explicitly specified template argument lists:
In contexts where deduction is done and fails, or [...], if a template argument list is specified and it, along with any default template arguments, identifies a single function template specialization, then the template-id is an lvalue for the function template specialization.
How does this apply to parameter packs?
Consider
template<typename...>
struct S {
S(int) {}
};
template<typename... A>
void f(S<A...>) {}
int main() {
f<int>(0);
}
This compiles on MSVC, but not on GCC and Clang, see godbolt. It would also be my intuition that it should fail, because deduction will fail, but the quote above seems to imply that even if deduction fails, since f<int> (in my understanding) identifies uniquely a template specialization, f<int> should be considered to refer to that specialization and then call it, without overload resolution, which will work, implicitly converting 0 to S<int>.
What is wrong in my understanding of the quote or is MSVC indeed correct?
Note that if we try to call f<>(0); (which I guess should work by the considerations above) all three compilers refuse to compile.
Relevant for the question is also [temp.arg.explicit]/6 that tells us that implicit conversions on a function parameter (as you want above) are
if the parameter type contains no template-parameters that participate in template argument deduction. [ Note: Template parameters do not participate in template argument deduction if they are explicitly specified. [...] ]
So, now is the question if A... participates in template argument deduction. (At this point I wanto to note that OPs code compiles also under gcc/clang if we replace the parameter pack by one template parameter, as it should since it is explicitly specified).
One could argue that A... is explicitly specified and therefore does not participate in deduction. But I would argue that one is wrong. [temp.arg.explicit]/9 tells us that deduction can extend explicitly specified template argument lists. Hence, f<int>(S<int, char>{0}); is valid and A... is deduced to int, char. So in this case A... definitely participates in deduction. But since this call only differs from your call by the parameter, the deduction also has to take place in your call, too.
In other words f<int>(0); could also mean to call f<int, char> and as such, it does not specify a single function template specification.
It's irrelevant. There's no such thing as a function call "without overload resolution". CWG2092 makes this clear.
[temp.over]/1 controls (broken apart for readability; emphasis mine):
When a call to the name of a function or function template is written
(explicitly, or implicitly using the operator notation), template
argument deduction ([temp.deduct]) and checking of any explicit
template arguments ([temp.arg]) are performed for each function
template to find the template argument values (if any) that can be
used with that function template to instantiate a function template
specialization that can be invoked with the call arguments.
For each function template, if the argument deduction and checking succeeds,
the template-arguments (deduced and/or explicit) are used to
synthesize the declaration of a single function template
specialization which is added to the candidate functions set to be
used in overload resolution.
If, for a given function template,
argument deduction fails or the synthesized function template
specialization would be ill-formed, no such function is added to the
set of candidate functions for that template. The complete set of
candidate functions includes all the synthesized declarations and all
of the non-template overloaded functions of the same name. The
synthesized declarations are treated like any other functions in the
remainder of overload resolution, except as explicitly noted in
[over.match.best].
There is an open core language issue (issue 2055: Explicitly-specified non-deduced parameter packs) that is well related to this case.
From my understanding of what is implictly stated in this issue, the intent is that compilers should behave as MSVC but the standard is said not to be clear enough.

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.

Contexts in which pack expansions can occur

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])