C++11 Lambda Type

Whenever one creates a lambda, the type is always auto, so I was wondering, is the type that it is viewed as always the same type for every kind of lambda or does each lambda have its own unique 'type'? Like could I make a lambda, and then set it equal to a new lambda?

1
2
3
4
5
6
7
8
9
10
11
12


int main(){
  auto lambda = [&] (int x,int y) -> int{
    int res = x + y;
    return res;
  }
  lambda = [&] (int x,int y) -> int{
    int res = x - y;
    return res;
  }
}
Last edited on
Like could I make a lambda, and then set it equal to a new lambda?

Nope.

cppreference wrote:
The lambda expression is a prvalue expression of unique unnamed non-union non-aggregate class type, known as closure type, which is declared (for the purposes of ADL) in the smallest block scope, class scope, or namespace scope that contains the lambda expression.


-Albatross
Lambda's are basically just syntactic sugar. They don't allow anything that isn't possible without them. They are a convenience.

Their type is unspecified, but in general a lambda creates an object from a class something like Func below. However, it's allowed to create a simple function instead if that is possible.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>

class Func {
    int& x;
public:
    Func(int&x) : x(x) {}
    void operator() (int a, int b) { std::cout << a + b + x << '\n'; }
};

int main() {
    int x = 7;
    auto f = [&x](int a, int b){std::cout << a + b + x << '\n';};
    f(2, 3);

    auto g = Func(x);
    x = 9;
    g(3, 4);
}

Last edited on
Whenever one creates a lambda, the type is always auto

Well, auto isn't a type, per se: it's a placeholder for a real type that the compiler must be able to deduce.

If we try to get the type of a lambda expression by saying decltype([](){}), we'll find that we are forbidden (until C++20) because the expression e in decltype(e) is an unevaluated expression and lambda expressions cannot appear in an unevaluated context;
if we try to say decltype(lambda), we'll find that the type is not very useful, because the type of the closure has a deleted default constructor (until C++20).
Last edited on
@theDaemoness ah darn it.
which is declared (for the purposes of ADL) in the smallest block scope ... that contains the lambda expression.
interesting.. so this might not work?
1
2
3
4
5
auto lambda;
if(1 == 1){
  lambda = [] (int x) -> int { return x + 23; } 
}
int z = lambda(10);


@dutch this actually might solve my new problem actually.

@mbozzi That’s actually the very reason I’m asking this question lol.
@dutch wait nope it doesn’t. Darn it.
That doesn’t mean this question wasn’t solved by the way everyone, I decided that what I was trying to do was stupid thanks guys! 😃
auto lambda; is meaningless. What type would lambda be? You need an initializer with auto.

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
#include <functional>

int main(int argc, char**) {
    std::function<void(int,int)> f;
    if (argc > 1)
        f = [](int a, int b) { std::cout << a + b << '\n'; };
    else
        f = [](int a, int b) { std::cout << a - b << '\n'; };
    f(3, 2);
}
Last edited on
I decided that what I was trying to do was stupid thanks guys!
Well, the question you asked was fine on its own. Still, you might get more useful help if you ask directly about your problem, instead of about a potential solution.
Those mis-directed questions are examples of XY problems:
http://xyproblem.info/
Last edited on
@dutch well yes, but does that mean that I can’t just initialize it right after declaration

@mbozzi but that wouldn’t leave any of the fun for me, and besides my ideas are usually ridiculous so I would probably just get a bunch of comments discouraging the idea instead of helping me with it. The solutionproblem was already solved, I was just trying to make it better (believe it or not XD).
Edit: ok I do see your point with the xy thing now though. Still for this one specifically I wouldn’t say it really applied since it was already solved.
Last edited on
well yes, but does that mean that I can’t just initialize it right after declaration

No. Of course not.
Instead of typing every brain-burp of a question, maybe think first.
auto's point is to avoid having to type out types, either because you want the type of a variable to be easy to change later, or to avoid being redundant, or to save yourself a lot of typing for long type names like some_collection<some_type, some_other_template_argument>::difference_type.

That variable's type still needs to be known when it's declared, and C++ adds a further restriction that those variables need to be initialized when they're declared. Otherwise, it'd be more complicated for the compiler to figure out what type the variable's supposed to have, to say nothing of the programmers who have to read that code.

EDIT from the future: Repeater also brings up a good point about auto in templates. It's certainly a lot more pleasant to use auto there than having to decltype everything (or worse, add a new template parameter). Otherwise, there's a lot of uses for auto, including template<auto>, that I didn't really touch on.

-Albatross
Last edited on
I feel I should add to Albatross' comment that another, very valuable use of auto, is in templates. To my mind this is far more valuable than the other uses. It allows things that simply could not be done in previous version of C++.

This page shows an example, but use of auto in templates goes beyond just this example: http://thbecker.net/articles/auto_and_decltype/section_04.html
Last edited on
@Repeater/TheDaemoness But I’ve tried to use auto for templates before, I thought it was illegal? I see what you mean though of course, I guess that was a fluke.
@dutch sorry, your right, I was just kinda responding. I’ll think next time.
I don't know how you tried to use "auto for templates", so I can't comment about what was or wasn't illegal about that.

However, auto being allowed for non-type template parameters is moderately new, having been introduced with C++17.

-Albatross
🤷‍♂️ I honestly don’t even remember. It just didn’t work is all I know.
Topic archived. No new replies allowed.