如何理解“只能在参数声明中使用椭圆抽象符号的抽象声明符号”

4
考虑以下引用,它说:
[dcl.fct]/16

在声明符或抽象声明符中包含省略号只能用于参数声明。[...]

我同意“在声明符中包含省略号只能用于参数声明”,因为我们不能在任何地方使用类似于“...id-expression”的东西,它只能出现在参数声明中,所以这是100%清楚的。然而,关于“抽象声明符中包含省略号只能用于参数声明”,请考虑下面的代码:
#include <iostream>
#include <tuple>
template<typename...T>
void func(T...){
  std::tuple<T...> tup;  //#1
}

【dcl.name】

类型标识符:

类型说明符序列 抽象声明符(可选)

关于#1,它并不是参数声明,然而在该上下文中包含省略号的抽象声明符被用于类型标识符。那么,我的关于抽象声明符的理解是否有误呢?

1个回答

5
省略号不是type-id的一部分,而是template-argument-list的一部分。

如果我们应用[temp.names]中的以下语法:

simple-template-id:
    template-name < template-argument-listopt >
template-name: identifier template-argument-list: template-argument ...opt [...]
template-argument: type-id [...]

对于你的例子,我们得到:

   std::tuple<T...> tup;
//      tuple<T...>       simple-template-id
//      tuple             template-name
//            T...        template-argument-list
//            T           template-argument, type-id

然后,[temp.arg]/9

紧随省略号的模板参数是一个包扩展。

这就是我们所期望的。


你的意思是这里出现的省略号不是抽象声明符的一部分,而是跟在模板参数后面。那么是否存在抽象声明符的情况呢? - xmh0511
@jackX 没错。在你的例子中,void func(T...) 中的省略号是一个 抽象声明符,位于一个 参数声明 中。 - Mark
我不理解元组中的 T... 和参数列表子句中的 T... 之间的区别,我认为它们都是类型标识符。换句话说,元组中的模板参数也是类型,对吗?就像你回答中的语法一样,template-argument: type-idT 是类型名称,... 是抽象声明符。这是我的理解。有没有引用可以将它们区分开来? - xmh0511
是的,但是模板名称可以跟随 <something>,而这里的 T 只是某种类型,它不是模板名称,我认为。 而且 [temp.param#3] 表示它是一个 typedef 名称,这意味着它必须表示一种类型,相比之下,模板名称不是一种类型。 - xmh0511
正如你所说,在行模板 typename... T 中,这是遵循省略号的情况,因此标识符 T 不是 typedef 名称。[[temp.param]/3] 表示“在模板声明的范围内”,因此我认为 T... 符合这些规则。这是我的理解,我不能百分之百确定。 - xmh0511
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接