我们什么时候可以省略 C++11 lambda 中的返回类型?

2021-12-23 00:00:00 lambda c++ c++11 type-deduction

据我知道,在标准 C++11 (not C++14),当省略 lambda 的返回类型时,其返回类型被推导出为:

As far as I know, in standard C++11 (not C++14), when omitting the return type of a lambda, its return type is deduced to be:

  1. 返回表达式的类型,只要 lambda 只包含一个带有表达式的 return 语句,或者
  2. void 在所有其他情况下.
  1. The type of the returned expression, whenever the lambda consists of nothing but a single return statement with an expression, or
  2. void in all other cases.

现在考虑这个代码:

#include <iostream>

auto closure = [](int x)
{
    x++;
    return x;
};

int main()
{
    int y = closure(10);
    std::cout << y << std::endl;
}

这应该属于第 2 种情况.但是,在 g++4.9.2、g++5 和 clang++ 中,代码的编译就像带有 auto 类型推导的 C++14,使用 -pedantic -Wall -Wextra -std=c++11.这里发生了什么?我对标准的解释有误吗?

This should fall under case 2., however the code compiles as if were C++14 with auto type deduction, in both g++4.9.2, g++5 and clang++, with -pedantic -Wall -Wextra -std=c++11. What's going on here? Am I interpreting the standard wrong?

推荐答案

您的代码在没有任何警告的情况下被接受,因为最初的 C++11 限制被认为是标准中的一个缺陷,它允许实现来修复行为.参见 CWG DR975,DR1048 和 N3638.

Your code is being accepted without any warnings because the original C++11 restriction is considered a defect in the standard, which allows implementations to fix the behavior. See CWG DR975, DR1048 and N3638.

975.对 lambda 的返回类型推导的限制

[在 2013 年 4 月的会议上作为论文 N3638 的一部分转移到 DR 状态.]

[Moved to DR status at the April, 2013 meeting as part of paper N3638.]

似乎没有任何技术困难需要当前的限制,即只有当 lambda 的主体由单个 return 语句组成时才能推导出 lambda 的返回类型.特别是,如果它们都返回相同的类型,则可以允许多个 return 语句.

There does not appear to be any technical difficulty that would require the current restriction that the return type of a lambda can be deduced only if the body of the lambda consists of a single return statement. In particular, multiple return statements could be permitted if they all return the same type.

1048.自动推导和 lambda 返回类型推导.

...

2014 年 11 月会议的笔记:

CWG 同意论文 N3638 中体现的更改应被视为针对 C++11 的 DR.

总而言之,DR975 建议修改 lambda 表达式的返回类型推导规则,以允许多个 return 语句.

In summary, DR975 proposed modifying the rules for return type deduction for lambda expressions to allow multiple return statements.

DR1048 指出了一个差异,即使用占位符类型 auto 推导出正常函数的返回类型的规则与 DR975 中提出的规则略有不同.具体来说,普通函数的返回类型推导将在所有情况下丢弃顶级 cv 限定符,而 lambda 表达式的返回类型推导将保留类类型的 cv 限定符.

DR1048 identifies a discrepancy where the rules for deducing the return type for normal functions using the placeholder type auto differs slightly from the rules proposed in DR975. Specifically, return type deduction for normal functions would discard top-level cv-qualifiers in all cases, where as those for lambda expressions would preserve cv-qualifiers for class types.

N3638 解决了这个问题.

N3638 resolves this issue, amongst others.

我怀疑除了在实现上述 DR 之前找到一个附带 C++11 lambda 支持的编译器版本之外,还有什么方法可以恢复到原始行为.

I doubt there's any way to revert to the original behavior short of finding a compiler version that shipped with C++11 lambda support prior to the implementation of the DR above.

相关文章