Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

#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.

like image 699
user8063157 Avatar asked Jun 27 '18 10:06

user8063157


People also ask

How do I compile with GCC instead of Clang?

If you want to use clang instead of GCC, you can add -DCMAKE_C_COMPILER=/path/to/clang -DCMAKE_CXX_COMPILER=/path/to/clang++ . You can also use ccmake , which provides a curses interface to configure CMake variables.

Is GCC compatible with Clang?

Yes, for C code Clang and GCC are compatible (they both use the GNU Toolchain for linking, in fact.) You just have to make sure that you tell clang to create compiled objects and not intermediate bitcode objects. C ABI is well-defined, so the only issue is storage format.

Which compiler is better GCC or Clang?

Clang is a C, C++, Objective-C, or Objective-C++ compiler that is compiled in C++ based on LLVM and released under the Apache 2.0 license. Clang is mainly used to provide performance superior to that of GCC. Through long-term development and iteration, GCC, Clang, and LLVM have become mature compilers in the industry.

Is Clang and GCC the same?

Clang is designed as an API from its inception, allowing it to be reused by source analysis tools, refactoring, IDEs (etc) as well as for code generation. GCC is built as a monolithic static compiler, which makes it extremely difficult to use as an API and integrate into other tools.


1 Answers

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.

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.)

like image 148
aschepler Avatar answered Sep 28 '22 17:09

aschepler