Hi, Andrew Schepler.  

Maybe you misread these rules. For my example, namely `T&&...args`, the pack expansion occurs in a function parameter pack, that is said, the rule [temp.variadic#4.1] applies to this example.
That means, "the pattern is the parameter-declaration without the ellipsis."(namely T&& args) . In addition, what the exactly meaning of "The instantiation of a pack expansion that is neither a sizeof... expression nor a fold-expression produces a list of elements E_1, E_2, ..., E_N, where N is the number of elements in the pack expansion parameters... if the pack is a template parameter pack" is that, for  `T&&...args` where `T` is a template parameter pack, it's a pack expansion. As aforementioned , the pattern for `T&&...args` is `T&& args`, such form is the pattern for `Ei` which would be generated  by instantiating  such a pattern. Note though, this sentence "and replacing each pack expansion parameter with its i-th element.", that means, the element is the corresponding value of the template parameter as said in [temp.variadic#7.1].  such as, the deduced template argument is `int&` when I pass a lvalue of type `int` as the unique argument, that means, the collection of `pack expansion parameters` only has one element which is `int&`, and such a element is used to replace the corresponding pack expansion parameter which is a component of the pattern. So the result of such an instantiation of the pattern would be `int&&& args1`(hypothetical form), then the reference collapsing should be performed for such a declaration. However within this hypothetical declaration,  `int&` is neither a typedef-name or  decltype-specifier.  It violates the rule [dcl.ref#6]. So, I don't think these rule is ok.

Andrew Schepler <aschepler@gmail.com> 于2020年9月4日周五 下午6:43写道:
>
> I think the Standard is okay here.
>
> The name T of the template parameter pack certainly isn't a typedef-name: we can't have "T var;" or "T&& var;". It's only inside a pack expansion where T should obey this rule, as in (T&&... args) in this example, or std::tuple<T&&...> var;, or etc.
>
> And I think the rules for instantiating pack expansions in [temp.variadic] do qualify T inside an expansion for the reference collapsing rule.
>
> [temp.variadic]/(5.3):
>>
>> In a template parameter pack that is a pack expansion ([temp.param]):
>>
>> if the template parameter pack is a type-parameter; the pattern is the corresponding type-parameter without the ellipsis.
>
>
> [temp.variadic]/8:
>>
>> The instantiation of a pack expansion that is neither a sizeof... expression nor a fold-expression produces a list of elements E_1, E_2, ..., E_N, where N is the number of elements in the pack expansion parameters. Each E_i is generated by instantiating the pattern and replacing each pack expansion parameter with its i-th 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 ([temp.param]) of the corresponding kind (type or non-type) designating the i-th corresponding type or value template argument;
>
> So when the template parameter pack is instantiated in func<int, char>, the pattern is "typename T", then T is replaced with the invented type template parameters E_i. We can either interpret "its identifier" for such a parameter E_i to be the T in the pattern, or consider each E_i to act as if it has a unique unspellable identifier since it replaces T. Either way the identifier does not follow an ellipsis, so E_i is a typedef-name.
>
> On Wed, Sep 2, 2020 at 8:49 AM jim x via Std-Discussion <std-discussion@lists.isocpp.org> wrote:
>>
>> About the reference collapsing, its rule is defined as the  following:  
>>
>> >If a typedef-name ([dcl.typedef], [temp.param]) or a decltype-specifier denotes a type TR that is a reference to a type T, an attempt to create the type “lvalue reference to cv TR” creates the type “lvalue reference to T”, while an attempt to create the type “rvalue reference to cv TR” creates the type TR.  
>>
>> However, consider such a case:  
>> ````
>> template<typename...T>
>> void func(T&&...args){
>> }
>> int main(){
>>    int a{};
>>    char b{};
>>    func(a,b);
>> }
>> ````
>> we know the deduced template argument are `int&` and `char&`. That is, the function type is void(int&,char&). we know the reference collapsing rules is applying for this case. However, I have to say that the identifier `T` is neither a typedef-name nor decltype-specifier, because of the following rule:      
>>
>> 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.  
>>
>> So, these rules are contradicting with each others. How to interpret this? Is it a defect in the standard?
>> --
>> Std-Discussion mailing list
>> Std-Discussion@lists.isocpp.org
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion