C++ Logo

std-discussion

Advanced search

Re: The issue about reference collapsing for function parameter pack

From: Andrew Schepler <aschepler_at_[hidden]>
Date: Fri, 4 Sep 2020 06:43:26 -0400
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-04 05:47:08