Why this code fails to compile with gcc 4.8.5 while it compiles fine with 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);
}



Error below


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



clearly what I am referring to is local variable K and not const member K.





Are you sure you can compile it with Clang? You have names interception, since you are sharing constant 'k' with the lambda function formal parameter called k. If clang able to compile it - you probably can test it with GCC 5+ with -std=c++14 key. In any case you have an error in your code.
– Victor Gubin
Jun 29 at 11:25


-std=c++14





It fails with all the gcc compiler except 8.1 , we can see it here .godbolt.org/g/o355oQ
– user8063157
Jun 29 at 11:31






Perhaps relevant is that GCC 8.1 supports certain features of C++2a, so perhaps it's intentional.
– acraig5075
Jun 29 at 11:34





This has nothing to do with c++2a clang compiles it from version 3.4.1 onwards godbolt.org/g/B46sX9
– user8063157
Jun 29 at 11:36




1 Answer
1



This isn't quite as straightforward as it might seem. A lambda that captures k by copy is mostly equivalent to a struct object whose closure type has a member named k, and with an operator() whose definition uses the specified parameters and body. If that were technically true, sure, we know that a function parameter hides a class member.


k


k


operator()



Except that's not how the Standard actually defines lambdas. Instead, it says that any entity captured by value corresponds to an unnamed member of the closure type. In the lambda body, name lookup looks in the lambda's enclosing scope, not the scope of the closure type. If that name lookup finds an entity captured by copy, the compiler must internally transform that usage of the name to a usage of the unnamed member instead. In C++11 and C++14, these rules didn't clearly specify how lambda parameter names fit into that name lookup scheme, and as a result, different compilers and compiler versions didn't agree on behavior in cases like this where a captured entity and a lambda parameter had the same name.



With Defect Resolution 2211, C++17 solved the issue by just making it illegal:



[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 ]



(See also the same paragraph in the current draft mirror.)





Then this is a Bug with gcc 8.1 and clang I suppose , Which need to be reported. Clang: godbolt.org/g/B46sX9 gcc 8.1: godbolt.org/g/7p9tyZ
– user8063157
Jun 29 at 12:09







By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Comments

Popular posts from this blog

paramiko-expect timeout is happening after executing the command

Opening a url is failing in Swift

Export result set on Dbeaver to CSV