Search code examples
c++lambdaauto

Lambda black magic taking different types


Trying to find yet another way to simply serialize my code, I had the stupid idea to try this impossible thing. But it worked. I really wonder why:

template <typename C>
void f(C c)
{
    int a = 1;
    float b = 1.5f;
    c(a);
    c(b);
}

int main()
{
    f([](auto v){
        std::cerr << v << "\n";
    });
    return 0;
}

I looked at the resulting assembly (g++-9.3 -O0 -g -S -fverbose-asm test.cpp -o test.s), and it appears that two distincts lambdas are generated: one taking a float, and the other one taking an int. Is this black magic? Is there anyone who knows the standard and can explain more about this?


Solution

  • This call:

    f([](auto v){
            std::cerr << v << "\n";
        });
    

    is passing a generic lambda to f, as the argument c. A generic lambda is one that has a templated member operator(), because of the auto parameter.

    So when you make the following calls:

    c(a);  // int argument
    c(b);  // float argument
    

    the compiler will instantiate one version of the lambda's member operator() with int, and one version of the member operator() with float.