【问题标题】:Is there a special rule for lambda in case of decltype(auto)?在 decltype(auto) 的情况下,lambda 是否有特殊规则?
【发布时间】:2017-07-06 10:29:30
【问题描述】:

如果我理解正确this answer 并引用了标准部分[dcl.type.auto.deduct-5],代码:

decltype(auto) a = e;

总是等价于

decltype( e  ) a = e;

但是现在问题出现了,如果我将 lambda 表达式而不是 e 放入 decltype(auto):

decltype(auto) lambda = [](){};

令我惊讶的是,这在gccclang 中都成功编译了。我所经历的震惊的原因在于标准,它明确指出 lambda 不应该出现在未评估的操作数 [expr.prim.lambda#2](强调我的)中:

lambda 表达式是一个纯右值,其结果对象称为 闭包对象。 lambda 表达式不应出现在未计算的 操作数,在模板参数中,在别名声明中,在 typedef 中 声明,或在函数或函数模板的声明中 在其函数体和默认参数之外。

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

decltype([](){}) lambda = [](){};

上面显式编写的代码显然格式不正确。当然,我们可以假设 decltype 中的声明 [](){} 是一种引用,而不是像 structured bindings 那样的真正引用,但也许标准中有一条特殊规则我错过了涵盖 lambda正在初始化decltype(auto)?

【问题讨论】:

    标签: c++ lambda c++14 language-lawyer decltype


    【解决方案1】:

    此答案基于我对相关标准文本的解释。这些部分不是很清楚,意见分歧,因此目前很难知道它们的确切含义。似乎,排除可能的疏忽,主要编译器似乎都同意所讨论的定义确实格式正确。

    此外,我认为听到定义不正确会非常令人惊讶。


    我所经历的震惊的原因在于标准中明确指出 lambda 不应该出现在未评估的操作数中[...]

    您在哪里看到 lambda 出现在未评估的上下文中?

    decltype(auto) lambda = [](){};
    

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

    现在你的困惑可能是因为你似乎认为上面的陈述等同于

    decltype([](){}) lambda = [](){};
    

    但严格来说,情况并非如此。如果你看一下措辞的语言,有一个小的区别(我突出显示):

    如果占位符是decltype(auto)类型说明符,则T 应单独作为占位符。为T 推导的类型按照 [dcl.type.simple] 中的描述确定,因为虽然e 一直是decltype 的操作数。

    这里的关键词是虽然。这只是意味着推演就像decltype(e)一样发生,这意味着decltype的推演规则适用于auto操作数e的推演规则。

    这里,操作数 e 确实是 lambda,但这是完全合法的,因为标准要求行为与您编写 decltype([](){}) 时的行为相同好像,这意味着decltype 的扣除规则适用于 lambda。现在[expr.prim.lambda]/2在这里不适用,因为lambda不在未求值的上下文中,所以编译器使用decltype([](){})推导类型实际上是合法的,这意味着decltype规则必须用于lambda。

    当然,如果你写decltype([](){}),程序格式不正确,但这里不是这样,如上所述。

    在这种情况下,因为 lambda 表达式是纯右值,所以推导的类型应该只是 lambda 的类型。

    至少我是这么理解的……

    【讨论】:

    • 两个编译器团队像你一样独立理解它,所以你很有可能是对的。还是如你所说it is not completely equivalent不应该有严格的解释规则吗?
    • @W.F.:“不应该有一个严格的规则来解释它”有一个严格的规则;他只是为你引用了它。这就是为什么“两个编译器团队”做对了。
    • @W.F.我认为this clause 明确禁止使用带有decltype(auto) 的花括号初始化列表
    • @Rakete1111 不,这里没有return 声明。这是被禁止的,因为花括号初始化列表不是表达式。
    • 我不同意,它明确表示“为 T 推导的类型是按照 [dcl.type.simple] 中的描述确定的,好像 e 是 decltype 的操作数一样。”,这意味着出现了推导好像你写了decltype([](){}),这是非法的。非法代码sn-p是什么意思?换句话说,当e是一个lambda表达式时,“它只是意味着使用decltype的规则来推导e”是什么意思?
    猜你喜欢
    • 2017-04-07
    • 1970-01-01
    • 2018-04-16
    • 1970-01-01
    • 2016-09-27
    • 2011-09-14
    • 2013-04-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多