Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are my lambda parameters really shadowing my locals?

I'm dealing with some C code that takes some data, and forwards it to the function passed in:

void foo(int* data, void (*fun)(int*)){
  (*fun)(data);
};

The following works without warning:

void bar(int* data){};

int main(){
  int data=0;
  foo(&data,bar);
}

However, if I use a lambda instead:

int main(){

  int data=0;
  foo(&data,[](auto data){});
}

I get the following warning:

warning: declaration of ‘data’ shadows a previous local [-Wshadow]
   foo(&data,[](auto data){});
                         ^
o.cpp:14:7: note: shadowed declaration is here
   int data=0;

But I thought an empty capture group would exclude the first instantiation during its look up.

Is this warning legitimate?
Why isn't the empty capture enough to avoid warnings?

like image 905
Trevor Hickey Avatar asked May 24 '16 03:05

Trevor Hickey


1 Answers

Names from the enclosing scope of the lambda are also in the scope of the lambda.

Names that are not captured may still be used, so long as they are not odr-used. Only odr-used variables must be captured. Example:

#include <iostream>

template<typename T> void foo(const int *, T f) { std::cout << f(5) << '\n'; }

int main()
{
    const int data=0;
    foo(&data,[](int baz){
        return data;
    });
}

Because reading a constant expression is not odr-use, this code is correct and data refers to the variable in main.

This program outputs 0, but if you change int baz to int data, it outputs 5.

like image 66
M.M Avatar answered Sep 23 '22 08:09

M.M