【问题标题】:The wording about instantiation of a pack expansion in [temp.variadic][temp.variadic] 中关于包扩展实例化的措辞
【发布时间】:2020-06-29 02:48:06
【问题描述】:

我想知道下面引用中的措辞是否有误,即

temp.variadic#7

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

  • 如果包是模板参数包,则元素是相应类型(类型或非类型)的模板参数,指定模板参数的类型或值;否则,
  • 如果包是函数参数包,则元素是一个id-expression,用于指定函数参数,该函数参数由声明包的模式的实例化产生。

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

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

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

通常的参数声明包括:

  • attribute-specifier-seq (opt) decl-specifier-seq 声明符
  • attribute-specifier-seq (opt) decl-specifier-seq declarator = initializer-clause
  • attribute-specifier-seq (opt) decl-specifier-seq abstract-declarator(opt)
  • attribute-specifier-seq (opt) decl-specifier-seq abstract-declarator (opt) = initializer-clause

无论如何,decl-specifier-seq 不是可选组件。

在这个例子中

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

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

【问题讨论】:

    标签: c++ c++17 language-lawyer


    【解决方案1】:

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

    1. 函数参数包是接受零个或多个函数参数的函数参数。
    什么是函数参数包?

    在 c++17 标准中,它说:

    dcl.fct#16

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

    这听起来像是一个参数声明,其中 declarator-id 或 abstract-declarator 包含省略号,并且这样的参数声明出现在参数声明子句中,这样的参数声明是一个函数参数包。对吧?

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

    dcl.fct#21

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

    它表示一个参数声明,其中包含省略号的声明符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...) 这样的某些情况,包args 是曾经是这种包扩展的模式,这种包扩展的实例化将是id-expression,指定来自模式T args的实例化的函数参数。

    【讨论】:

    • @LanguageLawyer 我已仔细阅读标准并在此答案中写下理解。
    • args 是函数参数包,因为 args 是函数参数 为什么 args 而不是 ...argsT...args 是函数参数? func(T...)中,没有参数?
    • 暗示参数是一个实体你认为这解释了为什么args而不是T...args是参数吗?
    • @LanguageLawyer 我已经更新了我的答案,c++17和最新的草案有一些区别,最新的草案可以解释为什么args是。
    • @LanguageLawyer 非正式地。 T args是参数声明,这样的声明声明了一个参数,即args
    【解决方案2】:

    在该包扩展中,T args 被扩展(即使后者被声明为一个包);因此,生成的 parameter-declaration 具有 T1 args1,T2 args2,… 的形式,并正确配备了 decl-specifier

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-21
    • 2020-02-17
    • 1970-01-01
    • 2013-07-04
    • 2019-11-02
    相关资源
    最近更新 更多