一个非捕获的变量可以被lambda参数遮蔽吗?

Gam*_*ama 4 c++ lambda shadow clang++

我有一个看起来像这样的代码 - 它大大简化了,但这个代码片段编译并展示了相同的行为:

template <typename TFunc>
float FloatSelect( const float in_value, TFunc&& Predicate) {
  return std::forward<TFunc>(Predicate)(in_value) ? in_value : 0.0f;
};

void DisplayFloatSelect() {
  const float value = FloatSelect(
    -1.0f,
    [] (const float value) { return value > 0.0f; }
  );

  std::cout << value << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

随着-Wshadow使编译器发出如下警告(如看到这里):

12 : warning: declaration shadows a local variable [-Wshadow]

[] (const float value) { return value > 0.0f; }

^

10 : note: previous declaration is here

const float value = FloatSelect(

^
Run Code Online (Sandbox Code Playgroud)

哪个不是真的有用 - 我理解变量的阴影是什么,但是因为lambda没有捕获任何东西,所以在这里应该没问题.

我错过了什么?

ric*_*ici 10

是的,非捕获变量可以被lambda参数遮蔽.

在OP中lambda的特定情况下,你可能会认为内部声明value不会影响外部声明的范围,因为lambda没有捕获.尽管如此,外部value可以在lambda的主体内部看到,因为lambda的主体仍然在封闭块的范围内:

(C++14§5.1.2/ p.7):lambda-expression的复合语句产生函数调用操作符的函数体(8.4),但为了查找名称(3.4),确定类型和这个(9.3.2)的值和使用(*this)(9.3.1)将非静态类成员转换为类成员访问表达式的idexpressions转换,在lambda表达式的上下文中考虑复合语句.

来自外部作用域的非捕获变量的使用是一个错误,但是如果没有捕获的lambda可能使用在外部作用域中定义的名称,如果它不是odr-use(并且在这样的情况下)例如,捕获变量.)特别是,可以使用const外部范围的变量:

const int i = 20;
int f = ([](){return i + 3;})();
Run Code Online (Sandbox Code Playgroud)

因此,即使lambda没有捕获,名称的显式参数i肯定会影响外部i.(请参阅http://coliru.stacked-crooked.com/a/006f5f20cca841d5 ;您可能想尝试启用-Wshadow.)

由于-Wshadow准确地用于揭示这种模糊的名称用法,因此在OP中的情况下触发警告似乎并不太令人惊讶.

-Wshadow-Wall既不是-Wextra正确的,也不正是因为它经常会警告你关于你并不真正关心的事情.