为什么此代码无法使用 gcc 4.8.5 进行编译,而使用 clang 可以正常编译

Why this code fails to compile with gcc 4.8.5 while it compiles fine with clang

#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 而不是常量成员 K。

这并不像看起来那么简单。通过复制捕获 k 的 lambda 主要等同于一个结构对象,其闭包类型具有一个名为 k 的成员,并且具有一个 operator(),其定义使用指定的参数和主体。如果这在技术上是正确的,当然,我们知道函数参数隐藏了一个 class 成员。

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

对于 Defect Resolution 2211,C++17 通过将其设为非法解决了这个问题:

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

If an identifier in a simple-capture appears as the declarator-id of a parameter of the lambda-declarator's parameter-declaration-clause, the program is ill-formed. [ Example:

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

-- end example ]

(另请参阅当前镜像中的 the same paragraph。)