Lambda expression in C ++, OS X clang vs GCC

A specific property of C ++ lambda expressions is to capture variables in the area in which they are declared. For example, I can use the declared and initialized variable c in a lambda function, even if "c" is not sent as an argument, but it is captured by "[]":

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

The expected result is 10. The problem occurs when at least two variables, one of which is written and the other sent as an argument, have the same name:

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

I think the 2011 standard for C ++ says that the captured variable takes precedence in the arguments of the lambda expression in case of a name match. In fact, compiling the code using GCC 4.8.1 on Linux means I get the expected 5 . If I compile the same code using the apple version of the clang compiler (clang-503.0.40, the one that comes with Xcode 5.1.1 on Mac OS X 10.9.4), I get a different answer 3 .

I am trying to understand why this is happening; is it just an Apple compiler error (if the standard for the language really says that the captured "c" takes precedence) or something like that? Can this problem be fixed?

EDIT

My teacher sent an email to the GCC help desk and they replied that this was clearly a GCC compiler error and report it to Bugzilla. So Clan behavior is right!

+8
gcc lambda c ++ 11 clang macos
source share
2 answers

From C ++ 11, 5.1.2 "Lambda Expressions" [expr.prim.lambda] # 7:

lambda-expression s compound operator gives the functional body (8.4) of the function call operator, but for the purpose of searching by name (3.4), defining the type and value of this (9.3.2) and converting id-expression s referring to non-static members of the class into access expressions to class members using (*this) (9.3.1), the compound statement is considered in the context of a lambda expression .

Also, from 3.3.3 "Block Area" [basic.scope.local] # 2:

A potential domain of a function parameter name (including one included in the lambda-declarator ), or a function, a local predefined variable in the definition of function (8.4), starts from its declaration point.

Names in the capture list are not declarations and therefore do not affect the name search. The capture list allows you to use only local variables; he does not enter their names in the lambda region. Example:

 int i, j; int main() { int i = 0; [](){ i; }; // Error: Odr-uses non-static local variable without capturing it [](){ j; }; // OK } 

So, since the parameters for the lambda are in the inner area of ​​the block, and since the name is searched in the context of the lambda expression (not, say, the generated class), the parameter names really hide the variable names in the attached function.

+1
source share

From my understanding of the following standard C ++ 11 clauses:

5.1.2 Lambda Expressions

3 The type of lambda expression (which is also the type of the closure object) is a unique, unnamed type of non-unit class - the closure type - whose properties are described below.

...

5 The closure type for a lambda expression has an open function call operator (13.5.4), whose parameters and return type are described by the parameter-declaration-lambda-expression-sentence and trailing-return-type, respectively. This function call statement declared const (9.3.1) if and only if lambda expressions parameter-declaration-sentence should not be mutable.

...

14 For each object captured by the copy, an unnamed non-static data element is declared in the closure type.

A lambda expression like this ...

 int c = 5; [c](int c){ std::cout << c << '\n'; } 

... roughly equivalent to class / structure as follows:

 struct lambda { int c; // captured c void operator()(int c) const { std::cout << c << '\n'; } }; 

So, I would expect this option to hide the captured element.

EDIT:

In paragraph 14 of the standard (above), it would seem, a data element created from a captured variable, * unnamed * . The mechanism by which it refers, apparently, does not depend on the search for normal identifiers:

17 Each id-expression that is unacceptable (3.2) of the object captured by the copy is converted to access the corresponding unnamed data element of the closure type.

It is not clear from my reading of the standard if this conversion should take precedence over the search for a parameter character.

So, perhaps this should be marked as UB (undefined behavior)?

+2
source share

All Articles