Search

7.15 — Introduction to lambdas (anonymous functions)

Consider this snippet of code that we introduced in lesson 6.18 -- Introduction to standard library algorithms:

This code searches through an array of strings looking for the first element that contains the substring “nut”. Thus, it produces the result:

Found walnut

And while it works, it could be improved.

The root of the issue here is that std::find_if requires that we pass it a function pointer. Because of that, we are forced to define a function that’s only going to be used once, that must be given a name, and that must be put in the global scope (because functions can’t be nested!). The function is also so short, it’s almost easier to discern what it does from the one line of code than from the name and comments.

Lambdas to the rescue

A lambda expression (also called a lambda or closure) allows us to define an anonymous function inside another function. The nesting is important, as it allows us both to avoid namespace naming pollution, and to define the function as close to where it is used as possible (providing additional context).

The syntax for lambdas is one of the weirder things in C++, and takes a bit of getting used to. Lambdas take the form:

[ captureClause ] ( parameters ) -> returnType
{
    statements;
}

The capture clause and parameters can both be empty if they are not needed.

The return type is optional, and if omitted, auto will be assumed (thus using type inference used to determine the return type). While we previously noted that type inference for function return types should be avoided, in this context, it’s fine to use (because these functions are typically so trivial).

Also note that lambdas have no name, so we don’t need to provide one.

As an aside...

This means a trivial lambda definition looks like this:

Let’s rewrite the above example using a lambda:

This works just like the function pointer case, and produces an identical result:

Found walnut

Note how similar our lambda is to our containsNut function. They both have identical parameters and function bodies. The lambda has no capture clause (we’ll explain what a capture clause is in the next lesson) because it doesn’t need one. And we’ve omitted the trailing return type in the lambda (for conciseness), but since operator!= returns a bool, our lambda will return a bool too.

Type of a lambda

In the above example, we defined a lambda right where it was needed. This use of a lambda is sometimes called a function literal.

However, writing a lambda in the same line as it’s used can sometimes make code harder to read. Much like we can initialize a variable with a literal value (or a function pointer) for use later, we can also initialize a lambda variable with a lambda definition and then use it later. A named lambda along with a good function name can make code easier to read.

For example, in the following snippet, we’re using std::all_of to check if all elements of an array are even:

We can improve the readability of this as follows:

Note how well the last line reads: “return whether all of the elements in the array are even

But what is the type of lambda isEven?

As it turns out, lambdas don’t have a type that we can explicitly use. When we write a lambda, the compiler generates a unique type just for the lambda that is not exposed to us.

For advanced readers

In actuality, lambdas aren’t functions (which is part of how they avoid the limitation of C++ not supporting nested functions). They’re a special kind of object called a functor. Functors are objects that contain an overloaded operator() that make them callable like a function.

Although we don’t know the type of a lambda, there are several ways of storing a lambda for use post-definition. If the lambda has an empty capture clause, we can use a regular function pointer. In the next lesson, we introduce lambda captures, a function pointer won’t work anymore at that point. However, std::function can be used for lambdas even if they are capturing something.

The only way of using the lambda’s actual type is by means of auto. auto also has the benefit of having no overhead compared to std::function.

Unfortunately, we can’t always use auto. In cases where the actual lambda is unknown (e.g. because we’re passing a lambda to a function as a parameter and the caller determines what lambda will be passed in), we can’t use auto. In such cases, std::function should be used.

Output

0
1
2

Rule

Use auto when initializing variables with lambdas, and std::function if you can’t initialize the variable with the lambda.

Generic lambdas

For the most part, lambda parameters work by the same rules as regular function parameters.

One notable exception is that since C++14 we’re allowed to use auto for parameters (note: in C++20, regular functions will be able to use auto for parameters too). When a lambda has one or more auto parameter, the compiler will infer what parameter types are needed from the calls to the lambda.

Because lambdas with one or more auto parameter can potentially work with a wide variety of types, they are called generic lambdas.

For advanced readers

When used in the context of a lambda, auto is just a shorthand for a template parameter.

Let’s take a look at a generic lambda:

Output:

June and July start with the same letter

In the above example, we use auto parameters to capture our strings by const reference. Because all string types allow access to their individual characters via operator[], we don’t need to care whether the user is passing in a std::string, C-style string, or something else. This allows us to write a lambda that could accept any of these, meaning if we change the type of months later, we won’t have to rewrite the lambda.

However, auto isn’t always the best choice. Consider:

Output:

There are 2 months with 5 letters

In this example, using auto would infer a type of const char*. C-style strings aren’t easy to work with (apart from using operator[]). In this case, we prefer to explicitly define the parameter as a std::string_view, which allows us to work with the underlying data much more easily (e.g. we can ask the string view for its length, even if the user passed in a C-style array).

Generic lambdas and static variables

One thing to be aware of is that a unique lambda will be generated for each different type that auto resolves to. The following example shows how one generic lambda turns into two distinct lambdas:

Output

0: hello
1: world
0: 1
1: 2
2: ding dong

In the above example, we define a lambda and then call it with two different parameters (a string literal parameter, and an integer parameter). This generates two different versions of the lambda (one with a string literal parameter, and one with an integer parameter).

Most of the time, this is inconsequential. However, note that if the generic lambda uses static duration variables, those variables are not shared between the generated lambdas.

We can see this in the example above, where each type (string literals and integers) has its own unique count! Although we only wrote the lambda once, two lambdas were generated -- and each has its own version of callCount. To have a shared counter between the two generated lambdas, we’d have to define a variable outside of the lambda. For now, this means defining the variable even outside of the function the lambda is defined in. In the above example, this means adding a global variable. We’ll be able to avoid the global variable after talking about lambda captures in the next lesson.

Return type deduction and trailing return types

If return type deduction is used, a lambda’s return type is deduced from the return-statements inside the lambda. If return type inference is used, all return statements in the lambda must return the same type (otherwise the compiler won’t know which one to prefer).

For example:

This produces a compile error because the return type of the first return statement (int) doesn’t match the return type of the second return statement (double).

In the case where we’re returning different types, we have two options:
1) Do explicit casts to make all the return types match, or
2) explicitly specify a return type for the lambda, and let the compiler do implicit conversions.

The second case is usually the better choice:

That way, if you ever decide to change the return type, you (usually) only need to change the lambda’s return type, and not touch the lambda body.

Standard library function objects

For common operations (e.g. addition, negation, or comparison) you don’t need to write your own lambdas, because the standard library comes with many basic callable objects that can be used instead. These are defined in the <functional> header.

In the following example:

Output

99 90 80 40 13 5

Instead of converting our greater function to a lambda (which would obscure its meaning a bit), we can instead use std::greater:

Output

99 90 80 40 13 5

Conclusion

Lambdas and the algorithm library may seem unnecessarily complicated when compared to a solution that uses a loop. However, this combination can allow some very powerful operations in just a few lines of code, and can be more readable than writing your own loops. On top of that, the algorithm library features powerful and easy-to-use parallelism, which you won’t get with loops. Upgrading source code that uses library functions is easier than upgrading code that uses loops.

Lambdas are great, but they don’t replace regular functions for all cases. Prefer regular functions for non-trivial and reusable cases.

Quiz time

Question #1


Create a struct Student that stores the name and points of a student. Create an array of students and use std::max_element to find the student with the most points, then print that student’s name. std::max_element takes the begin and end of a list, and a function that takes 2 parameters and returns true if the first argument is less than the second.

Given the following array

your program should print

Dan is the best student

Show Hint

Show Solution

Question #2

Use std::sort and a lambda in the following code to sort the seasons by ascending average temperature.

The program should print

Winter
Spring
Fall
Summer

Show Solution


7.16 -- Lambda captures
Index
7.14 -- Ellipsis (and why to avoid them)

69 comments to 7.15 — Introduction to lambdas (anonymous functions)

  • SORT(CONFUSING)

    This sort part makes me confused.
    Here it says:

    https://en.cppreference.com/w/cpp/container/list/sort

    comp - comparison function object (i.e. an object that satisfies the requirements of Compare) which returns ​true if the first argument is less than (i.e. is ordered before) the second.

    When first element is less that the second one it returns true. It means if averageTemperature of the first season < averageTemperature of the second season then returns true, which means the first one should be swapped with the second one, so the second one which is greater than comes before the first one: This means with '<' OPERATOR, it should be descending but it is sorted in ascending. I didn't get that part!

    • nascardriver

      > When first element is less that the second one it returns true. It means if averageTemperature of the first season < averageTemperature of the second season then returns true That's right. > which means the first one should be swapped with the second one
      That's wrong. The first one gets swapped with the second if the second should be ordered before the first. `std::sort` sees that first should be ordered before the second, so it doesn't swap them.

  • Barhram

    I changed the last statement of the code, and I had no idea why the "averageTemperature" was printed as integer numbers not double

    Also, is there any reason that for 'Student' std:string was used but for season "std::string_view"?

    • nascardriver

      Doubles are printed as integers if they have nothing after the decimal point. If you change a temperature to say 296.1, it will be printed as 296.1.

      Seasons don't change. There are 4 seasons and they always have the same name, so we can use `std::string_view` onto a string literal. This is faster and cheaper than using `std::string`.
      Students are people and people names aren't constant, there is a huge number of name and they'll likely be input by the user (Though, this isn't the case in this example). The value of the name cannot be a string literal, it has to be owned by the `Student` struct, so we use `std::string`.

  • lambdas aren’t functions

    >>In actuality, lambdas aren’t functions

    >>If the lambda has an empty capture clause, we can use a regular function pointer.

    How come lambdas aren't function but we can store them as a function pointer and consider their types as function pointer?

    >>Only works with with an empty capture clause.
    there is extra 'with'

    • nascardriver

      Lambdas are a class-type. Their most prominent member function is `operator()` which is used to call to lambda as if it were a function. If a lambda has an empty capture list, it has another member function that allows conversion to a function pointer.
      This might be too much to grasp now, we cover these concepts later in the tutorial.

      Thanks for pointing out the typo :()

      • lambdas aren’t functions

        Thank you dear Nascadriver. You are genius :)

        The more I learn about this amazing and beautifully designed programming language, C++, the more I get amazed! It really keeps blowing my mind. And you guys have played a very important role in showing the beauty of this language. I have fallen in love with C++ a lot. thank YOU.

  • Nexteon

    Hello, I am back after a house renovation. The first quiz question confused me. Here the code.

    In other words, why is it that since max_elements returns a bool that Points is a struct?

    • nascardriver

      `std::max_element` returns an iterator (similar to a pointer) to the found element (or `arr.end()` if `arr` is empty).
      `std::max_element` only use `mostPoints` to compare the elements in `arr`, but `std::max_elements` doesn't return a `bool`.

  • Alek

    hey,``As it turns out, lambdas don’t have a type that we can explicitly use. When we write a lambda, the compiler generates a unique type just for the lambda that is not exposed to us``.
    why don't I get it :(.
    doesn't the lambda have a return type ? isn't tht type the type of lambda ?
    can you explain this to me ?
    2:also after this I was curious about functions too.the type of function isn't the same with type of return type right ? and I asked about it in a discord group someone said if for example we have a function like below: int func(int x,string c); the type of function would be int(int,string) is it right ?

    thanks in advance.

    • nascardriver

      In lesson F.7.8, we have shown function pointers. Those are (almost) the types of functions. If functions had the same type as their return type, you could do this

      • Alek

        so for a function pointer like this :

        so this is a function pointer but can you tell me now how can I infer the type of function from this ? is it like the thing I sais above ?
        is it int(int,std::string) ?
        one thing else to note:
        ``But what is the type of lambda isEven?
        As it turns out, lambdas don’t have a type that we can explicitly use. When we write a lambda, the compiler generates a unique type just for the lambda that is not exposed to us.``
        I put that line of code in VS and it says isEven is a bool.the lambda type is a unique type as you say but isEven has the same type of lambda's return type not itself type.
        thanks!

        • nascardriver

          The type of the function is `int(int, std::string)`. `isEven` is not a `bool`, it has a unique type.

          • Alek

            thanks for your answer.now I understand why when I hover over it,it says it's a bool because it shows the return type of it.but it's a lambda itself.

            • nascardriver

              Then VS is wrong. You can always check if 2 types are the same by using `std::is_same_v`

  • Tim

    I ran the last example of the tutorial before conclusion without the header files <algorithm> and <functional> and it still compiled fine (see down below).

    Could you explain why this works (and even if it works, why we should include <algorithm> and  <functional>)?

    Thank you in advance!

    • nascardriver

      It works with your compiler and your standard library, because array or iostream include the headers your need themselves. This is non-standard behavior, your code won't work on other people's systems. Include everything you use.

  • Robbie Williams

    Hey guys, thanks for all the hard work. Just slightly confused as to what std::max_element returns. On cppreference it says it returns an iterator (which is if I remember correctly like a pointer that points to the element in an array), which begs the question, if we don't use auto in

    what would we use instead? I understand that auto makes the code a lot cleaner but I'm trying to avoid using it too much to make sure I understand what type everything returns. I tried defining a new student as the result of max_element, but then I read that it returns an iterator. Since I have tried

    and

    which seemed most logical to me, but as you know, neither compile... Just really confused honestly :') Thanks for all the hard work you do!

  • Dal

    Sorry struggling with this one, could you advise where the original example at the opening of the tutorial is; before we get on to the subject of lamdas?

  • Hi guys, my thanks again for the great resource you guys have provided everyone here; free of charge.

    Just to update you both on my previous post, unsurprisingly there's nothing wrong with the code here.
    The issue was with my antivirus; Avast. Disabling Core Shields > File Shield enables the files to be built & linked correctly.

    Apologies for the false alarm again, & hopefully this helps someone another day.

  • Gabe

    Quiz 1:

  • turner

    Actually he said that lambdas doesnt have a explicit type we can use, well we actually have:

    []type()->type

    where "type" is the data type. Example: int

    so you can type:

    []int()->int lambda_func = [](){};

  • Al

    Note that in your first example inside the Generic Lambdas subsection you say that prior to C++17 we should initialize the array as

    but I think that std::string_view itself was added in C++17.

  • giang

    So, in the examples above, how the lamda functions in adjacent_find or max_element can know that 'const auto &a' and 'const auto &b' are adjacent? thanks for the lesson btw!!

    • nascardriver

      `std::adjacent_find` calls the function with adjacent elements, that's how it's defined. Similar to

  • Strato

    Thank you so much for all the hard work and an excellent course!
    I think in question #1 should be an

    for std::max_element

  • Lifthra

    "The root of the issue here is that std::find_if requires that we pass it a function pointer. Because of that, we are forced to define a function that’s only going to be used once, that must be given a name, and that must be put in the global scope (because functions can’t be nested!). The function is also so short, it’s almost easier to discern what it does from the one line of code than from the name and comments."

    Are there any reasons to use lambdas other than that?
    I still can't figure out how I should use lambdas, I find functions more clean and easy to read

    • nascardriver

      Once you write larger projects, you'll notice that it gets hard to find the right place for a tiny function. You can use regular functions for as long as you feel comfortable. At some point you'll realize that a lambda is better suited for the job.

  • Vir1oN

    Hi, thanks for the great lesson!
    I'm so glad that learncpp keeps covering new topics of C++.

    I also have a question about usage of generic lambdas.
    For example, in quiz solution for question #2, we wrote

    Is it a good idea in this case to use automatic type deduction, if we use a variable that is a member of a single struct Season?
    Why not prefer

    instead?

    • nascardriver

      For anyone who knows standard algorithms (That should be every C++ programmer who uses the standard library), it's well-known that the parameters of the function are elements of the container (`seasons`) we're passing to `std::sort`. Typing out the parameter types is long and redundant. Additionally, if we change the type of `season` to something that's convertible to `Season`, the elements will be converted to `Season`s in order to call the lambda. If we used `auto` parameters instead, we'd likely get a compile-time error, because the new type doesn't have a `averageTemperature` member.

  • Andy

    Hi!
    I don't understand the syntax "best->name"in solution to question #1, line 30. I remember in your previous lesson, you said "->" can be used when we want to access struct member via a pointer to a struct. But I don't think "best" is a pointer... Did I miss something in your lessons?

  • Kelvin

    Hi there!

    Is it maybe possible to make an extra notification that pops up when hovering above thee new- or/and updated signs. One that states when it was made new or when it was updated. Most usefull is the new notification i guess. Is this usefull or do you think otherwise?

  • Daniel

    Hi Guys,
    I've been trying to work out what the issue is with the solution to question 2. I've done the question, got it right and then checked the answer just to be sure. However I keep getting the error namespace std does not contain string_view. I fiddled around with it for a while, then copied and pasted the full solution into a blank file just to check I hadn't messed something up. It still wouldn't run, throwing the same error.
    Any clues?

    [Severity    Code    Description    Project    File    Line    Suppression State
    Error (active)    E0135    namespace "std" has no member "string_view"    Lambda (Temperature sort)    E:\Lambda (Temperature sort)\Lambda (Temperature sort)\Lambda (Temperature sort).cpp    8]

  • Ionut

    Nice lesson! Very neatly explained.

    Take this as a "constructive remark". You have two typos:

    One here: "(which would obscure it’s meaning a bit)"; "it's" should be "its".

    And one here: "Prefer a regular functions for non-trivial and reusable cases"; you should either omit the "a" or write the singular form "function" instead of "functions".

    Thank you guys a lot for doing this amazing job that you do! I am a student and it really helps a lot.
                                                                                                                            Wishing you all the best!

  • p1

    Even though i love this site this is one of the hardest lessons i've encountered so far.I guess i will come back to it later.

    • nascardriver

      Hi! Can you describe what's making this lesson harder for you?

      • p1

        Well first of all i kind of took a brake from learning cpp and continued so i just sprinted trough the previous chapters without any practice.Second i think it is a harder lesson and those 2 in combination tend to hurt so its just easier for me to continue and after some time come back with more knowledge.Im pertty ambitious as sometimes i just wonder in my head "what is this,when will i ever need any of this" and its probably cause im quite young and want to use this into making games.Again nothing to you guys you are all awesome for making this free and available for anyone,i dont think there is any better source for learning cpp,it is just me and my brain :).

        • nascardriver

          Thanks for replying :) You can keep going without lambdas. You'll have to understand them at some point, but maybe by then your cpp is fresh enough to have an easier time. If you have any specific questions when you revisit lambdas, please ask and I'll try to elaborate.

  • Kwonk

    Although this website is my go-to site for C++ tutorials, since you properly take time to explain things and do so in depth, this lesson left me very confused.

    "We can improve the readability of this as follows:"
    > You said the point of lambdas is that you wouldn't have to define a function. So what's the point of defining a lambda outside of a parameter?
    The only difference between lambdas and functions I see now is that the lambda can be defined inside of another function.

    "A regular function pointer."
    > Why can you save a lambda expression as a function pointer? How can a function pointer point to a lambda expression? I thought the whole point of lambdas is that they aren't functions.

    "The lambda can't capture anything."
    > What does it mean for a lambda to 'capture' something? It sounds like it has something to do with capture clauses, but then again, you told us not to worry about those since they will be discussed in the next lesson...

    "Using std::function. The lambda can capture variables."
    > What even is std::function? It is mentioned before in the lesson about function pointers, but nothing was said about it other than that it's an alternative to writing a function pointer.

    > You could argue that one way in which a lambda is more useful than a function is because parameters can be 'auto', but in that case you can just make a template parameter.

    > Speaking of those, I happen to know what a template parameter is, so I get what you mean when you say generic lambdas work with template parameters. But it seems that understanding how templates work is important for knowing how generic lambdas work (considering you had to write the whole part about static variables), which is annoying as templates are covered in a later chapter.

    I don't know... It feels like this lesson is placed too early in the tutorial series and like you're going over a lot of information too quickly.

    • nascardriver

      > what's the point of defining a lambda outside of a parameter?
      This will make more sense after you read the next lesson about lambda captures.

      > function pointer
      The type of a lambda has a special function that makes the lambda object callable (We talk about this later). You can have a pointer point to that function.

      > capture
      Lambda captures used to be in this lesson. I had another pass over this lesson to remove the talk about captures or make it sound less like the reader should be familiar with them.

      > std::function
      At this point in the lessons, we can't explain what `std::function` is or how it works. To do this, we need templates and operator overloading, which aren't covered until chapter 13. It doesn't make sense to move these lessons, because they depend on preceding lessons. For now, you only have to know how to use `std::function` and treat its implementation as magic.

      > template
      You don't need to understand how generic lambas work to use them, just like we've been using eg. `std::cout <<` from the beginning of the tutorials but are still in no condition to understand how it works. The lambda lessons _could_ be moved way back into the lessons so we could explain lambdas in detail, but that's not necessary and it would hold up other lessons. By explaining them here, we're able to use lambdas in all later lessons and readers can use them in quizzes and private code. I think this is more important than implementation details. We don't want to cover lambdas (And other language features) in detail in their first lesson. Understanding how to use a feature and what it does first is easier to digest than trying to understand everything at once. In the first lessons, we show how to use something, and look back at it after we've shown a different feature that the lesson made use of (eg. operator overloading will mention lambdas). At that point, it's trivial to explain the implementation. I think you experienced this lesson as a rush, because you know more about C++ than what was taught up to this lesson. This made you try to understand more than you need to. Thanks a lot for your specific feedback, it's much appreciated! If you disagree with something I said or want to add anything, please leave a reply (-:

      • Kwonk

        After reading over this lesson for a couple of more times (and the next one), it's starting to make more sense.

        I now get what the point of lambdas is indeed.

        I'm sure I'll get to understand all the stuff you've mentioned in later lessons as well.
        By the way, I don't have as much extra experience as you think ;D

        Anyway, thank you for responding!
        (and for listening to my feedback; I see you have updated the lesson a little bit :D )

        I will now continue to read through the tutorial!

  • Alexsander

    I didn't catch what's the point in having a lambda with a variable pointing to it, naming it, compared to writing a function. Other than having it's definition near to where it'll be used, it seems that writing a simple function would be more simple and intuitive.

    • nascardriver

      The `isEven` example in this lesson can be rewritten with a regular function. For one, you'd have to find a good place for an `isEven` function, which is hard to find in a real program. Using a lambda eliminates this problem. Though, you could write a regular function.
      Things start to get messy once the lambda captures something (next lesson). Then, in addition to a regular function, you'll have to use global variables (Or at least variables with a way bigger scope than required).
      Naming the lambda is mostly only required to make the code more readable or to use the lambda more than once. You'll probably see more use for named lambdas after knowing lambda captures. If you're still confused after the next lesson, please ask again.

  • kavin

    Hi, under generic lambdas example, line 26,

    return the entire strings "June" and "July" right? And thats why we are derferencing 'sameLetter'  in line 32?

    In line 32 we can also use *(sameLetter + 1) {from chap 6.8a) instead of *std::next(sameLetter) ? Because i think this is the 1st time we are using std::next() .

    • nascardriver

      `a` is a string and `b` is a string.
      `a[0]` is a char and `b[0]` is a char.
      `a[0] == b[0]` is a bool.
      This is unrelated to the return value of `std::adjacent_find`. `std::adjacent_find` returns an iterator the the first found element. We use the * operator to get the element an iterator is pointing to.

      > we can also use *(sameLetter + 1)
      If the container's iterators support the + operator, yes. Not all iterators do that. `std::next` works on all iterators than can be advanced forward.

  • Ged

    Question 1 In all my codes I have used std::vector instead of std::array. So I have a question. Is std::vector good for built in arrays as well. I'm talking about speed and everything. I keep hearing that the only array that you actually need to know is std::vector. Is this true?

    Question 2 [ std::begin(vector) and vector.begin() ] Are there any real differences between them or just the syntax?

    • nascardriver

      1
      That's wrong. Here's a good talk by Alan Talbot about standard containers. If you know all the values at compile-time, use a type that doesn't need a run-time, ie. `std::array`.

      2
      `std::begin(vector)` calls `vector.begin()`, there's no difference.

  • Suyash

    The concept of lambda expressions (or anonymous functions) is not a new one for me... And, the syntax is similar to other conventional implementations of this idea in other languages (like Arrow functions in JavaScript)...

    What confused me in the above problems was not related to the implementation of the lambdas but some things that I observed that I found peculiar in the given starting code...

    Why do we put an extra pair of braces when initializing the fixed-size arrays of Student or Season type in the above code?

    (And, yes I did read the answer that was presented in @Alex's link to a Stack Overflow question... But, while it solved some doubts, it raised countless others in its wake...)

    If I infer correctly from the answer, then std::array takes in an array and a type as its initialization values but only in the case of user-defined types (classes, struct, enum) but it isn't required for primitive data types(??)... And, only C-style array can be passed as an argument to its constructor or can
    we also pass other aggregate types like std::vector or even another std::array?

    I would love if you could provide an answer to this burning question or a link to a resource which could ably answer the above queries...

    Code in question...

    • nascardriver

      `std::array` doesn't have a custom constructor (nor a custom assignment operator), it's elements (A single c-style array), get initialized via aggregate initialization.
      The question about the extra braces is rather common, so I added a section about it to lesson S.6.15. Please let me know if this section helps.

      • Suyash

        Yeah, the section does help, especially the example with our own simple implementation of std::array...

        Thanks for adding this section... I am sure that it will benefit everyone...

  • sito

    hello! I'm a student and I'm currently going through the lessons here. I'm at chapter9 and saw that some new lessons were added. When should i come back to the new lessons? should i continue forward and revisit them at a later date or should i come back to them now before continuing on?

    • Alex

      If the lessons were added earlier in the lesson order than where you are, I'd jump back and read them, as future lessons may have been updated to incorporate those concepts.

  • Hassan Muhammad

    finally, i lived to see lambdas, thanks for the hardwork(seems we've two tutors already).
    By the way, i've finished the chapter on templates before coming back to this lesson and concerning the auto parameter functions(cpp 20), i though they could substitute templates(because of simplicity), right? or what will you recommend.
    keep up the good work and Have a nice day.

    • nascardriver

      `auto` parameters are a nice addition, but they can't replace template. Take this simple example

      There'll also be concepts in C++20, which need templates.

  • Connor

    Hi!

    Quick question, and it's probably a really obvious answer that for some reason is not clicking with me, but here we go:

    In the quiz questions, when creating our arrays I noticed that there is an extra curly brace and I'm not sure why. When I try to remove it , I get a "too many initializer values" error. But when I create an identical array using C-style arrays, I don't need the extra brace. Maybe I'm just missing something obvious but I thought I'd ask. Thanks :)

    Example:

    • Alex

      https://stackoverflow.com/questions/29150369/stdarray-aggregate-initialization-requires-a-confusing-amount-of-curly-braces has some good answers for this.

  • ZioYuri78

    Hey guys, super happy to see Lambda chapters!
    Just a heads up about the Generic lambdas and static variables example, on mine machine the result is different and looks like it generate a third version of the lambda for print("ding dong") because the callCounter is 0.

    0: hello
    1: world
    0: 1
    1: 2
    0: ding dong

    • nascardriver

      Hi!

      Thank you very much for running the code yourself and finding a mistake!
      Since `print` takes its parameter by reference, the `auto` turns into a `char` array, not into a `const char*`. "hello" and "world" have the same length, so they share a lambda. "ding dong" is longer, so another lambda is generated. Changing `print`'s parameter to plain `auto` (no reference) fixes it.
      I suppose I made the parameter const reference after running the code, without thinking about the consequences.

Leave a Comment

Put all code inside code tags: [code]your code here[/code]