[temp.variadic]中关于包扩展实例化的措辞

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

本文关键字:实例化 扩展 于包 temp variadic      更新时间:2023-10-16

我想知道下面引用的是否措辞错误

温度变量#7

既不是sizeof的包扩展的实例化。。。表达式或折叠表达式都不会产生列表E1、E2,。。。En,其中N是包扩展参数中的元素数。每个Ei都是通过实例化模式并用其第i个元素替换每个pack扩展参数而生成的。在实例化的上下文中,这样的元素被解释如下:

  • 如果包是模板参数包,则元素是指定模板参数的类型或值的相应类型(类型或非类型)的模板参数;否则
  • 如果pack是函数参数pack,则元素是一个id表达式,指定声明pack的模式实例化后产生的函数参数

函数参数包的模式是一个没有省略号的参数声明,因为它定义如下:
temp.variadic#4

包扩展由一个模式和一个省略号组成,其实例化在列表中产生零个或多个模式实例化(如下所述)。模式的形式取决于展开发生的上下文。包扩展可能发生在以下情况下:

  • […]
  • 在函数参数包([dcl.fct])中;模式是不带省略号的参数声明

通常的参数声明包括:

  • 属性说明符seq(opt)decl说明符seq声明符
  • 特性说明符seq(opt)decl说明符seq声明符=初始值设定项子句
  • 属性说明符seq(opt)decl说明符seq抽象声明符(opt
  • 属性说明符seq(opt)decl说明符seq抽象声明符(opt

在任何情况下,decl-specifier-seq都不是可选组件。

在本例中

template<typename...T>
void func(T...args){
}

T...args是函数参数包,其中T args是其模式。所以我的问题是,为什么函数参数包的模式实例化生成的元素是id-expression,而id-expression只是参数声明的声明器的一部分。

我试着回答这个问题,要理解这些句子,这些句子需要分成几个部分。

  1. 函数参数包是一个接受零个或多个函数参数的函数参数

什么是函数参数包?在c++17标准中,它说:

dcl.fct#16

包含省略号的声明符id或抽象声明符只能在参数声明中使用。这样的参数声明就是一个参数包。当它是参数声明子句的一部分时,参数包就是函数参数包。

这听起来像是一个参数声明,其中包含省略号的声明符id或抽象声明符和这样的参数声明出现在参数声明子句中,这样的参数宣言是一个函数参数包。正确的

现在,我们看看最新的草案是怎么说的:

dcl.fct#21

包含省略号的声明符id或抽象声明符只能在参数声明中使用。当它是参数声明子句的一部分时,参数声明声明一个函数参数包。

它说一个参数声明,其中包含省略号的声明符id或抽象声明符和这样的参数声明出现在参数声明子句中,就这里而言,它们是相同的,然而,不同之处在于这里,这样的参数宣言声明了一个函数参数包。这意味着T...args声明了一个函数参数包。

  1. 包扩展由一个模式和一个省略号组成,其实例化在列表中产生零个或多个模式实例化包扩展可以在以下上下文中发生:
  • 在函数参数包([dcl.fct])中;模式是不带省略号的参数声明

该语句表示在作为函数参数包的上下文中发生的包扩展,模式是不带省略号的参数声明。非正式地,对于这种情况T...args,其T...表示包扩展,并且T...args的模式是T args

包扩展的实例化。。。

  1. 如果包是函数参数包,则元素是指定函数参数的id表达式,该函数参数由声明包的模式的实例化产生

关于第三个项目符号,这个包不表示T,它是由参数声明声明的,作为第一个项目符号的分析。理解这句话的另一个要点是函数参数,它是由声明包的模式实例化产生的。如上所述,声明包的图案是T args。因此,强调句意味着function parameter是包扩展T...args的模式T args的这些实例化的结果,现在它证实了第二个项目符号,并且对于某些情况,如postfix-expression(args...),包CCD_ 17被用作这样的包扩展的模式,并且这样的包扩张的实例化将是指定来自模式CCD_ 19的实例化的函数参数的CCD_。

在该包扩展中,Targs被扩展(即使后者被声明为包);因此,得到的参数声明s具有T1 args1,T2 args2,…的形式,并且适当地配备有decl-specifier