【问题标题】:C++11 restrictions on lambda return typeC++11 对 lambda 返回类型的限制
【发布时间】:2014-12-28 20:00:57
【问题描述】:

我正在cppreference 上阅读有关如何推断 C++11 lambda 的返回类型的信息:

如果主体由单个return 语句组成,则返回类型是返回表达式的类型(在右值到左值、数组到指针或函数到指针隐式转换之后)

所以我认为这意味着 lambda 只能有一个 return 语句。但为什么它仍然适用于多个 return 语句?

这两个编译器上的compiles

auto f = [] (bool c1, bool c2) {
    if (c1) return 1;
    if (c2) return 2;
    else    return 3;
};

【问题讨论】:

  • 您链接到的页面也显示规则在 C++14 中发生了变化。我的第一个猜测是编译器即使在 C++11 模式下也实现了 C++14 规则。
  • @hvd 是的,这就是我的怀疑,但我仍然持怀疑态度。
  • FWIW,我检查了 C++11 所说的内容,它与您在网上找到的内容相匹配,所以是的,它应该生成编译时诊断。也就是说,实现 C++14 规则不会导致有效的 C++11 代码被拒绝,所以它可能只是一个小问题。

标签: c++ c++11 lambda return language-lawyer


【解决方案1】:

这有点不精确。 [expr.prim.lambda]/4:

如果 lambda-expression 不包含 lambda-declarator,则它是 好像 lambda-declarator()。如果 lambda-expression 确实 不包括 trailing-return-type,就好像 trailing-return-type 表示以下类型:

  • 如果复合语句的形式是

    { attribute-specifier-seqoptreturn 表达式 ; }

    左值到右值后返回表达式的类型 转换 (4.1)、数组到指针的转换 (4.2) 和 函数到指针的转换(4.3);

  • 否则,void

因此,只有当 lambda 表达式的整个主体仅包含一个单独的 return 语句时,才会推断返回类型。

在这种情况下,GCC 和 Clang 都不符合标准,因为它们会发出错误当且仅当两个 return 语句导致不一致的扣除时才发出消息。这是因为他们已经实现了 C++14 标准,即使存在多个 return 语句和/或多个其他语句,也会扣除返回类型。 [expr.prim.lambda]/4 指定

lambda 返回类型为auto,替换为 trailing-return-type 如果提供和/或从return 语句推导出来,如 7.1.6.4 中所述

§7.1.6.4/9

如果函数声明的返回类型包含占位符 type 有多个return 语句,返回类型推导为 每个return 声明。如果推导出的类型在每个中都不相同 推论,程序是非良构的。

【讨论】:

【解决方案2】:

它适用于您的示例,因为所有 return 语句都返回相同类型的值。但是尝试将第二个return 更改为不同的类型,例如:

auto f = [] (bool c1, bool c2) {
    if (c1) return 1;
    if (c2) return "";
    else    return 3;
};

用 clang++ 编译会产生以下错误:

main.cpp:3:13: error: return type 'const char *' must match previous return type 'int' when lambda expression has unspecified explicit
      return type
    if (c2) return "";
        ^
1 error generated.

【讨论】:

  • 他在问为什么允许多个 return 声明,尽管引用说了什么(可能只有一个)。这与返回表达式的类型无关。
  • @0x499602D2 不过,(不完整的)引用并没有说不允许多个 return 语句。完整的引用似乎确实暗示了这一点,但它根本不精确。
  • @KonradRudolph 这就是 OP 的想法。
猜你喜欢
  • 2012-09-20
  • 2014-02-23
  • 1970-01-01
  • 1970-01-01
  • 2012-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多