C++ Logo

std-discussion

Advanced search

Re: The issue about reference collapsing for function parameter pack

From: jim x <xmh970252187_at_[hidden]>
Date: Sun, 6 Sep 2020 22:01:03 +0800
Sorry, Andrew Schepler. I think I can't agree with you optional. Firstly,
the rule [temp.variadic#7]
<https://timsong-cpp.github.io/cppwp/n4659/temp.variadic#7> is only about
the instantiation of *pack expansion. * "typename...T" is not a pack
expansion, so [temp.variadic#7]
<https://timsong-cpp.github.io/cppwp/n4659/temp.variadic#7> can't apply to
this declaration which declare a template parameter pack. And for this
[temp.param#3] <https://timsong-cpp.github.io/cppwp/n4659/temp.param#3> rule,
I have a different understanding with yours,
>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.

This rule is totally about the parameter declaration. In other words,
`template<typename T>` where identifier `T` is defined as a typedef-name.
Conversely, For the form `template<typename...T>` , where T is not defined
as a typedef-name, because such declaration does not satisfy what the above
rule says, that is " A type-parameter whose identifier does not follow an
ellipsis defines its identifier to be a typedef-name (if declared without
template)". So, wherever such an identifier appear in, such an identifier
can't be considered as a typedef-name(it's determined by the declaration
where such a identifier appears). Such as, for this declaration `typedef
int Integer`, `Integer` is a typedef-name whatever the form where the such
a name appears.(Because the declaration declare such a name as a
typedef-name). But, I'm not 100% sure the exactly intent of [temp.param#3]
<https://timsong-cpp.github.io/cppwp/n4659/temp.param#3> is not what you
said, I have to say whether a name has a property or not is determined by
its declaration which introduced the name and such a property appertains to
such a name , whatever how to use this name.



Andrew Schepler <aschepler_at_[hidden]> 于2020年9月5日周六 下午8:18写道:

> Oh, I think I missed a key point in your reading.
>
> 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&`,
>
>
> In the instantiation of "T&& ...args" when the template argument list is
> ("int&"), the parameter T is not replaced with the template argument "int&".
> It is replaced with the first (only) template parameter formed by the
> instantiation of "<typename... T>". That template parameter is a
> *typedef-name* which aliases int&.
>
> On Sat, Sep 5, 2020 at 8:12 AM Andrew Schepler <aschepler_at_[hidden]>
> wrote:
>
>> Hi again Jim,
>>
>> It is the declaration of a template type parameter, not any of its uses,
>> which makes it a *typedef-name*. Note the quoted 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."
>> is [temp.param]/3, and [temp.param] is entirely about interpretation of the
>> template parameters which appear in a "template <
>> *template-parameter-list*>" syntax.
>>
>> Taking the packs out of the picture, in
>>
>> template <typename T>
>> void func2(T&& arg) {}
>>
>> the identifier which does not follow an ellipsis is just the first
>> appearance of T, in the parameter declaration. Since it does not, T
>> becomes a *typedef-name* in the scope of the template; in particular,
>> where it is named in "T&& arg".
>>
>> (Even if the rule did apply to the function parameter pack "T&& ...args",
>> the identifier of the *type-parameter* is still T, not args, and T does
>> not "follow an ellipsis" in this syntax at all.)
>>
>> Andrew Schepler
>>
>>
>> On Sat, Sep 5, 2020 at 4:33 AM jim x <xmh970252187_at_[hidden]> wrote:
>>
>>> 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
>>>
>>

Received on 2020-09-06 09:04:46