Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

g++ won't allow generalized capture of const object by reference in lambda?

Tags:

c++

lambda

c++14

This is rejected by g++ (4.9.3 and 5.2.0), but is accepted by clang 3.5.0:

int main() { 
    const int ci = 0;
    auto lambda = [ &cap = ci ]() { };
}

g++ gives error: binding ‘const int’ to reference of type ‘int&’ discards qualifiers. It appears that g++ refuses to allow non-const references to be captured, except of course using plain old C++11 capture [&ci]. That seems a very strange constraint, perhaps a bug in g++?

like image 866
Aaron McDaid Avatar asked Aug 10 '15 12:08

Aaron McDaid


2 Answers

Your code is valid. §5.1.2/11 goes

An init-capture behaves as if it declares and explicitly captures a variable of the form
auto init-capture ;
whose declarative region is the lambda-expression’s compound-statement […]

Now, clearly, declaring

auto &cap = ci;

and capturing cap is fine. That is,

int main() { 
    const int ci = 0;
    auto &cap = ci;
    auto lambda = [&cap]() { };
}

compiles with GCC. Apart from the declarative region and lifetime of cap, there is no difference between this snippet and yours, thus GCC is incorrect.
This bug has already been reported as #66735, with a similar example:

int x = 0;
auto l = [&rx = static_cast<const int&>(x)] {};
like image 140
Columbo Avatar answered Nov 11 '22 19:11

Columbo


This looks similar to gcc bug: [C++14] lambda init-capture fails for const references which says:

This code fails to compile:

int main() {
    int x = 0;
    auto l = [&rx = static_cast<const int&>(x)]() {};
}

The error message is:

test.cpp:3:14: error: binding 'const int' to reference of type 'int&' discards qualifiers

auto l = [&rx = static_cast<const int&>(x)]() {

But according to [expr.prim.lambda]/11 rx should be captured as auto &rx = static_cast(x), that is as const int&.

the bug report references [expr.prim.lambda]/11 which says:

An init-capture behaves as if it declares and explicitly captures a variable of the form “auto init-capture ;” whose declarative region is the lambda-expression’s compound-statement, except that[...]

like image 4
Shafik Yaghmour Avatar answered Nov 11 '22 19:11

Shafik Yaghmour