返回的通用 lambda 的参数据称隐藏了自由函数的参数

Parameter of returned generic lambda allegedly shadows parameter of free function

编译以下代码

template <typename X, typename F>
auto apply(X x, F f)
{
    return f(x);
}

template <typename Y>
auto add_value(Y y)
{
    return [y](auto x)
    {
        return x + y;
    };
}

int main()
{
    apply(1, add_value(2));
}

with g++ (e.g. v. 5.4) 给出 shadow warnings.

$ g++ -Wshadow -Werror -std=c++14 shadow_test.cpp 
shadow_test.cpp: In instantiation of ‘add_value(Y)::<lambda(auto:1)> [with auto:1 = int; Y = int]’:
shadow_test.cpp:4:13:   required from ‘auto apply(X, F) [with X = int; F = add_value(Y) [with Y = int]::<lambda(auto:1)>]’
shadow_test.cpp:18:26:   required from here
shadow_test.cpp:10:22: error: declaration of ‘int x’ shadows a parameter [-Werror=shadow]
     return [y](auto x)
                      ^
shadow_test.cpp:2:14: note: shadowed declaration is here
 auto apply(X x, F f)
              ^
cc1plus: all warnings being treated as errors

我不明白为什么。谁能解释一下?

一定是一个错误。

  • 变量没有被隐藏,因为它不在 lambda 的封闭范围内,但它确实 produce the correct result
  • VS2015 不产生警告。
  • Clang 不产生警告。

这是推测,但可能发生的是以下替换(或类似的替换):

#include <iostream>

template <typename X, typename Y>
auto add_value(X x, Y y)
{
    auto f = [y](auto x)
    {
        return x + y;
    };
    return f(x);
}

int main()
{
    std::cout << add_value(1, 2);
}

这个节目does produce a shadow warning on Clang, but even then it produces the correct result. VS2015 still does not consider this worthy of a warning, but it is probably wrong because names from the enclosing scope of the lambda are also in the scope of the lambda. If they are not captured they may be used, but may not be odr-used as explained here.