在c ++中的Lambda表达式,OS X的clang vs GCC

pie*_*r94 8 macos lambda gcc clang c++11

c ++的lambda表达式的一个特定属性是捕获声明它们的作用域中的变量.例如,我可以在lambda函数中使用声明和初始化的变量c,即使'c'没有作为参数发送,但是它被'[]'捕获:

 #include<iostream>
 int main ()
 {int c=5; [c](int d){std::cout<<c+d<<'\n';}(5);}
Run Code Online (Sandbox Code Playgroud)

因此预期输出为10.当至少有两个变量(一个被捕获而另一个作为参数发送)具有相同的名称时,就会出现问题:

 #include<iostream>
 int main ()
 {int c=5; [c](int c){std::cout<<c<<'\n';}(3);}
Run Code Online (Sandbox Code Playgroud)

我认为2011年的c ++标准表明,在名称重合的情况下,捕获的变量优先于lambda表达式的参数.事实上,在Linux上使用GCC 4.8.1编译代码,我得到的输出是预期的,5.如果我使用apple的clang编译器编译相同的代码(clang-503.0.40,Mac OS X 10.9.4上的Xcode 5.1.1附带的那个),我得到另一个答案,3.

我想弄清楚为什么会这样; 它只是一个苹果的编译器错误(如果该语言的标准真的说捕获的'c'具有优先权)或类似的东西?这个问题可以修复吗?

编辑

我的老师给GCC服务台发了一封电子邮件,他们回答说这显然是GCC编译器的错误,并将其报告给Bugzilla.所以Clang的行为是正确的!

Eri*_*idt 1

来自 C++11 标准,5.1.2“Lambda 表达式”[expr.prim.lambda] #7:

\n\n
lambda表达式\xe2\x80\x99s复合语句生成函数调用运算符的函数this(8.4),\n但为了名称查找 (3.4) 的目的,确定(9.3.2) 的类型和值以及使用(9.3.1) 将引用非静态类成员的 id 表达式\n转换为类成员访问表达式,\n在lambda表达式上下文中考虑复合语句(*this)
\n\n

另外,从 3.3.3“块作用域”[basic.scope.local] #2 开始:

\n\n
函数参数名称(包括出现在lambda 声明符中的参数名称)或函数定义 (8.4) 中的函数局部预定义变量的潜在范围从其声明点开始。
\n\n

捕获列表中的名称不是声明,因此不会影响名称查找。捕获列表仅允许您使用局部变量;它不会将它们的名称引入 lambda 的作用域。例子:

\n\n
int i, j;\nint main()\n{\n    int i = 0;\n    [](){ i; }; // Error: Odr-uses non-static local variable without capturing it\n    [](){ j; }; // OK\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

因此,由于 lambda 的参数位于内部块作用域中,并且名称查找是在 lambda 表达式(而不是生成的类)的上下文中完成的,因此参数名称确实隐藏了封闭函数中的变量名称。

\n