在decltype(auto)的情况下,lambda是否有特殊规则?

W.F*_*.F. 11 c++ lambda decltype language-lawyer c++14

如果我正确理解了这个答案并引用了标准部分[dcl.type.auto.deduct-5],那么代码如下:

decltype(auto) a = e;
Run Code Online (Sandbox Code Playgroud)

总是相当于

decltype( e  ) a = e;
Run Code Online (Sandbox Code Playgroud)

但是现在问题出现了,而不是e我把lambda表达式放到decltype(auto):

decltype(auto) lambda = [](){};
Run Code Online (Sandbox Code Playgroud)

令我惊讶的是,这在gccclang中成功编译.我所经历的冲击的原因在于标准,其中特别指出lambda不应出现在未评估的操作数中[expr.prim.lambda#2](强调我的):

lambda-expression是一个prvalue,其结果对象称为闭包对象.lambda表达式不应出现在未评估的操作数,模板参数,别名声明,typedef声明或函数体和默认参数之外的函数或函数模板的声明中.

但正如我所提到的,这个例子相当于:

decltype([](){}) lambda = [](){};
Run Code Online (Sandbox Code Playgroud)

明确写出的上述代码显然是不正确的.当然,我们可以假设[](){}里面的语句decltype是一种引用,实际上并不是像结构化绑定那样的引用,但是标准中有一条特殊的规则,我错过了覆盖lambda的初始化decltype(auto)

Rak*_*111 7

这个答案是基于我对相关标准文本的解释.这些部分不是很明确,意见分歧,因此目前很难知道它们的确切含义.看来,除了可能的疏忽之外,主要编制者似乎都同意所讨论的定义确实是格式良好的.

此外,我认为听到定义不明确是非常令人惊讶的.


我所经历的冲击的原因在于标准,其中特别指出lambda不应出现在未评估的操作数中[...]

你在哪里看到lambda出现在未评估的背景中?

decltype(auto) lambda = [](){};
Run Code Online (Sandbox Code Playgroud)

我没有看到它,因为没有.lambda用作初始化器,完全合法.

现在你的混乱可能是因为你似乎认为上述陈述相当于

decltype([](){}) lambda = [](){};
Run Code Online (Sandbox Code Playgroud)

严格来说,情况并非如此.如果你看一下措辞的语言,就会有一点不同(由我强调):

如果占位符是  decltype(auto) 类型说明符T 则应仅为占位符.推导出的类型  T 是按照[dcl.type.simple]中的描述确定的,好像 e  它是操作数一样  decltype.

这里的关键词是,虽然.它只是意味着演绎就好像是decltype(e),这意味着decltype应用的演绎规则而不是auto操作数的演绎规则e.

在这里,操作e确实是拉姆达,但这是完全合法的,因为标准授权行为是相同的,就好像你会写decltype([](){}),这意味着的规则decltype扣除申请拉姆达.现在[expr.prim.lambda]/2不适用于此,因为lambda不在未评估的上下文中,因此编译器使用它decltype([](){})来推断类型实际上是合法的,这意味着decltype规则必须用于lambda.

当然,如果你写decltype([](){}),程序是不正确的,但如上所述,这不是这里的情况.

在这种情况下,因为lambda表达式是prvalue,所推导的类型应该只是lambda的类型.

至少那是我理解它的方式......

  • @Rakete1111不,这里没有'return`声明.它被禁止,因为braced-init-list不是表达式. (2认同)

归档时间:

查看次数:

421 次

最近记录:

8 年,6 月 前