13

我的书是这样说的:

具有函数主体的 Lambda 包含除未指定返回类型的单个 return 语句以外的任何内容返回 void。

但是这个:

auto f = []{
  int i=0; i++;
  return std::string("foo");
};
std::cout << f() << std::endl;

实际上编译并打印出“foo”,但是 lambda expr 不仅仅是一个返回语句,所以它应该返回 void,因为它没有手动指定“-> std::string”作为返回类型。

这里发生了什么?

我在最新的 Xcode 4.6 中使用 Apple 的编译器,基于 Clang 3.2 似乎:

铿锵——版本

Apple LLVM 版本 4.2 (clang-425.0.24)(基于 LLVM 3.2svn)目标:x86_64-apple-darwin12.2.0 线程模型:posix

4

5 回答 5

6

该书准确地反映了标准草案 n3290 中的规则。也许您的编译器实现了不同的草案。

在第 5.1.2p4 节中,草案内容如下

如果lambda 表达式不包含trailing-return-type,则好像trailing-return-type表示以下类型:

  • 如果复合语句的形式为 { 属性说明符序列选择 return 表达式 ; } ,则在左值到右值转换、数组到指针转换和函数到指针转换之后返回的表达式的类型;
  • 否则无效。

句法构造属性说明符序列可以是alignas或双括号属性。不是变量声明。

在 C++11 发布之后的 n3485 草案(即,它正在朝着 C++1y 发展)包含相同的措辞。我不知道在 n3290 之前的某些草案中是否有不同的规则。

于 2013-02-06T20:43:41.023 回答
3

如果您使用流行的编译器(gcc、Visual Studio),您通常不需要指定返回类型,只要编译器能够明确地确定它 - 就像在您的示例中一样。

以下示例显示了一个 lambda,它需要显式返回类型信息:

auto lambda = [](bool b) -> float
    { 
        if (b) 
            return 5.0f; 
        else 
            return 6.0; 
    };

我就此事询问了 Bjarne Stroustrup,他的评论是:

I do not know if C++11 allows the deduction of the return type is there are several return statements with identical return type. If not, that's planned for C++14.

于 2013-02-06T20:41:14.193 回答
1

我不确定从问题中的引用中得到什么,但这是 C++11 标准对没有声明符或返回类型的 lambdas 所说的:

如果 lambda-expression 不包含 lambda-declarator,就好像 lambda-declarator 是 ()。如果 lambda 表达式不包含 trailing-return-type,就好像 trailing-return-type 表示以下类型 (5.1.2p4):

— 如果复合语句的形式为 { attribute-specifier-seqopt return expression ; 左值到右值转换(4.1)、数组到指针转换(4.2)和函数到指针转换(4.3)后返回表达式的类型;

——否则,无效。

于 2013-02-06T20:46:01.307 回答
1

Clang 实现了对C++ 核心问题 975的建议解决方案。这允许 lambda 的任意主体,具有任意数量的 return 语句,并从返回的表达式中推断出返回值,但条件是它们都必须产生相同的类型。

在 C++14 中,N3638 进一步推广了这种支持该标准在 WG21 的布里斯托尔会议上被投票纳入该标准的工作草案。

于 2013-05-06T06:39:17.317 回答
0

草案 n3485 表明,如果编译器可以明确确定返回类型,它将允许 lambda 不指定它。

于 2013-02-06T20:44:58.217 回答