2

Here is a code snippet I have created:

    auto f = [](auto a) -> auto {
        cout << a << endl;
        return a;
    };

    cout << f(12) << endl;
    cout << f("test");

Here is what I know: Types have to be all resolved / specified at compile time.

The question here is, how is the compiler behaving when it sees this lambda function f? How does it deduces all the types for specific use like in line 6 and 7, in which we can see there are two different arguments passed for each call of lambda function f. Is the compiler creating different instances of the lambda function f to match the types passed?

Any help will be appreciated!

Also, if the answer is going to be too technical to be written on a few lines, I'd appreciate for any good reference on lambda functions and how they work.

One thing I have noticed, is that auto is not allowed when defining functions the usual way:

void f(auto a)
{

}

this does not compile.

Luke II
  • 31
  • 4
  • which `auto` do you mean? The type of the lambda or the type of its argument, or both? – 463035818_is_not_an_ai Jun 20 '22 at 11:09
  • the type arguments and return type of f specifically. – Luke II Jun 20 '22 at 11:10
  • A generic lambda is just an anonymous class with a template member function `operator()`. A compiler will generate two member functions, one for each argument type. – Evg Jun 20 '22 at 11:13
  • 1
    *this does not compile* - [Try a C++20 compiler](https://godbolt.org/z/96Y7P8vTe). – Evg Jun 20 '22 at 11:15
  • So the compiler is basically creating this anonymous class and then use it like a class template? – Luke II Jun 20 '22 at 11:15
  • 1
    No, a non-template class which has a member function template named `operator()`. – aschepler Jun 20 '22 at 11:16
  • 1
    The class itself is not a template, the member function is. – Evg Jun 20 '22 at 11:16
  • 2
    Worth noting that the C++20 `void f(auto a);` declaration is similarly a function template (so it should be defined in a header if declared in a header, and so on). – aschepler Jun 20 '22 at 11:18
  • This is all done internally before even compiling any code am I right? – Luke II Jun 20 '22 at 11:18
  • It's part of the compiling process. It may be in a compiler's "front end" logic for understanding C++ rather than its "back end" for generating architecture-specific assembly code, if that's similar to what you mean. – aschepler Jun 20 '22 at 11:20
  • Yes, I think I know what you mean. Front end logic for understanding C++ in the sense that there is even more code to generate outside of what has been written in the source code before even going like you said to the "Back end side" for generating assembly code. – Luke II Jun 20 '22 at 11:22
  • If we're talking about backends, note that for a simple lambda function a compiler might just inline it and generate no function calling code at all. – Evg Jun 20 '22 at 11:30
  • So it seems like depending the context a compiler will generate one construct or another. Clear! It goes without saying that the auto keyword used for defining the lambda function 'f' itself will work as a normal type deduction as if I were to declare auto e = 1; for example. – Luke II Jun 20 '22 at 11:33
  • 1
    *will work as a normal type deduction* - Yes, that's correct. – Evg Jun 20 '22 at 11:39

1 Answers1

5

Lambda is mostly equivalent to functor class:

struct Lambda
{
    template <typename T>
    auto operator()(T a) const
        std::cout << a << std::endl;
        return a; // make auto deduce as T
    }
};

f(12) would instantiate Lambda::operator()<int> and f("test") would instantiate Lambda::operator()<const char*>.

Jarod42
  • 203,559
  • 14
  • 181
  • 302