g ++不允许在lambda中通过引用对const对象进行广义捕获?

时间:2015-08-10 12:13:39

标签: c++ lambda c++14

这被g ++(4.9.3和5.2.0)拒绝,但被clang 3.5.0接受:

int main() { 
    const int ci = 0;
    auto lambda = [ &cap = ci ]() { };
}

g ++给出了error: binding ‘const int’ to reference of type ‘int&’ discards qualifiers。似乎g ++拒绝允许捕获非const引用,当然除了使用普通的旧C ++ 11捕获[&ci]。这似乎是一个非常奇怪的约束,也许是g ++中的一个错误?

2 个答案:

答案 0 :(得分:12)

您的代码有效。 §5.1.2/ 11去了

  

init-capture 表现,好像它声明并显式捕获形式的变量
auto init-capture ;
,其声明区域为 lambda-expression 复合语句 [...]

现在,显然,宣布

auto &cap = ci;

并且捕获cap很好。也就是说,

int main() { 
    const int ci = 0;
    auto &cap = ci;
    auto lambda = [&cap]() { };
}

compiles with GCC。除了cap的声明区域和生命周期之外,此片段与您的片段没有区别,因此GCC不正确。
此错误已报告为#66735,其中包含类似示例:

int x = 0;
auto l = [&rx = static_cast<const int&>(x)] {};

答案 1 :(得分:4)

这类似于gcc bug: [C++14] lambda init-capture fails for const references,其中包含:

  

此代码无法编译:

int main() {
    int x = 0;
    auto l = [&rx = static_cast<const int&>(x)]() {};
}
     

错误消息是:

     
    

test.cpp:3:14:错误:将'const int'绑定到'int&amp;'类型的引用     丢弃限定符

auto l = [&rx = static_cast<const int&>(x)]() {
  
     

但是根据[expr.prim.lambda] / 11 rx应该被捕获为auto   &amp; rx = static_cast(x),即const int&amp;。

错误报告引用 [expr.prim.lambda] / 11 ,其中说:

  

init-capture的行为就像它声明并显式捕获“auto init-capture”形式的变量一样。   其声明区域是lambda表达式的复合语句,除了[...]