为什么此代码无法在gcc 4.8.5中编译而在clang中可以正常编译

时间:2018-06-27 10:33:44

标签: c++ c++11 gcc clang gcc4.8

#include<iostream>                                                                                                                                    

using namespace std;                                                                                                                                  

int main()                                                                                                                                            
{                                                                                                                                                     
   const int k = 10;                                                                                                                                  

   // Capture k by value                                                                                                                              
   auto myl = [k] (int k) { cout << " ++k=" << ++k ; };                                                                                            

   myl(k+10);                                                                                                                                             
}  

下面的错误

lamda.cpp: In lambda function:
lamda.cpp:10:50: error: increment of read-only variable âkâ
    auto myl = [k] (int k) { cout << " ++K=" << ++k ; };

很明显,我指的是局部变量K,而不是const成员K。

1 个答案:

答案 0 :(得分:4)

这并不像看起来那样简单。通过副本捕获k的lambda等效于其闭包类型具有名为k的成员以及具有定义使用指定参数和主体的operator()的struct对象。如果从技术上讲是正确的,那么可以肯定,我们知道函数参数会隐藏类成员。

除非标准实际上不是这样定义lambda的。相反,它说任何由值捕获的实体都对应于闭包类型的 unnamed 成员。在lambda主体中,名称查找在lambda的包围范围内,而不是在闭合类型的范围内。如果该名称查找找到了由副本捕获的实体,则编译器必须在内部将名称的用法转换为未命名成员的用法。在C ++ 11和C ++ 14中,这些规则没有明确指定lambda参数名称如何适合该名称查找方案,结果,在以下情况下,不同的编译器和编译器版本在行为上没有达成共识:捕获的实体和lambda参数具有相同的名称。

使用Defect Resolution 2211,C ++ 17通过将其视为非法来解决了该问题:

[expr.prim.lambda.capture] / 5:

  

如果简单捕获中的标识符显示为 lambda-declarator的参数的 declarator-id , / em>的 parameter-declaration-clause ,该程序格式不正确。 [示例:

void f() {
  int x = 0;
  auto g = [x](int x) { return 0; } // error: parameter and simple-capture have the same name
}
     

-示例]

(另请参见当前草稿镜中的the same paragraph。)