C++ Logo

STD-DISCUSSION

Advanced search

Subject: Re: The issue about reference collapsing for function parameter pack
From: jim x (xmh970252187_at_[hidden])
Date: 2020-09-05 03:32:57


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]
<https://timsong-cpp.github.io/cppwp/n4659/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]
<https://timsong-cpp.github.io/cppwp/n4659/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]
<https://timsong-cpp.github.io/cppwp/n4659/dcl.ref#6>. So, I don't think
these rule is ok.

Andrew Schepler <aschepler_at_[hidden]> 于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_at_[hidden]> 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_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion



STD-DISCUSSION list run by std-discussion-owner@lists.isocpp.org

Older Archives on Google Groups