Parameter of returned generic lambda allegedly shadows parameter of free function

484 views Asked by At

Compiling the following code

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

I do not understand why. Can anybody explain?

1

There are 1 answers

7
wally On BEST ANSWER

Must be a bug.

  • The variable is not being shadowed as it is not in the enclosing scope of the lambda, however it does produce the correct result.
  • VS2015 produces no warnings.
  • Clang produces no warnings.

This is speculative, but what is probably happening is the following substitution (or something like it):

#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);
}

This program 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.