C++ Lambda Idioms - Timur Doumler - CppCon 2022

Поділитися
Вставка
  • Опубліковано 23 гру 2024

КОМЕНТАРІ • 68

  • @wolpumba4099
    @wolpumba4099 Рік тому +10

    *Introduction*
    - 0:00: Introduction by Timo Dumler, Developer Advocate at JetBrains.
    - 0:19: Discussion about how lambdas work and its evolution over different C++ standards.
    - 0:32: Discussion about various programming patterns and techniques involving lambdas.
    - 0:57: Explanation about some useful lambda techniques and curiosities about the language.
    - 1:21: Goal to teach everyone at least one new thing about lambdas in C++.
    *Lambda Expressions*
    - 1:29: Introduction to Lambda expressions in C++.
    - 1:35: Example of using a lambda expression in a standard algorithm.
    - 2:11: Explanation of how lambdas work in C++11.
    - 2:33: Explanation about the generation of closure type when a lambda expression is written.
    - 2:57: Explanation about the unnamed temporary instance of the closure type generated by the compiler.
    - 3:56: Discussion on the const by default nature of the inline call operator.
    - 4:20: Discussion on the deduction of return type by the compiler.
    - 4:49: In C++11, lambdas are not default constructible and not assignable.
    *Unary Trick* (ugly hack, don't use)
    - 6:16: Introduction to the Unary trick.
    - 7:35: Demonstration of using the unary plus operator to implicitly convert a lambda to a function pointer.
    - 8:11: Explanation about how the *unary plus operator* works with pointers and lambda expressions.
    *Captures*
    - 8:31: Discussion started on capitalist lambdas
    - 8:37: Introduced concept of captures in Lambdas
    - 8:44: Explained that captures are variables from the Lambda's scope
    - 8:49: Assumed listeners have a basic understanding of the concept
    - 8:54: Variables can be captured by value or by reference
    - 9:07: Talked about explicit captures and mixed captures
    - 9:13: Discussed what happens under the hood during capture with the compiler
    - 9:20: Example given of capturing two variables, I and J, by value
    - 9:25: Compiler adds private members data to closure type and initializes them
    - 9:37: Noted that the names and order of members are unspecified
    - 10:18: Explained you cannot name the members, can only refer to the variable that was captured
    - 10:30: Discussed capture by reference and potential compiler optimizations
    - 10:55: The standard allows more flexibility for optimization opportunities
    - 11:30: If captured by value, the value of the captured variables cannot be modified inside the Lambda
    - 11:55: Discussed the ability to *capture 'this'* (dangerous; subtle differences between standards of how 'this' is captured by value or reference) in a class and call members and member functions
    *Local Variables*
    - 13:10: Introduced the concept of capturing local variables
    - 13:15: Noted that only local variables can be captured
    - 13:20: Discussed an example of a *static object not being captured*
    - 13:32: Mentioned that the same rule applies for global variables
    - 13:44: Explained that variables are not captured unless the Lambda odr uses them
    - 14:03: Discussed const expert variables and how they are not odr used
    - 14:55: Mentioned const variables of integer type are implicitly const expert and not odr-used (One Definition Rule)
    - 16:01: Noted that float types must be captured as they're not integer types
    *Immediately Invoked Functions*
    - 16:35: Discussed the use of immediately invoked functions/ lambdas
    - 16:59: Explained the usefulness of this idiom in complex object initialization scenarios
    - 17:26: Example given of immediately invoking a Lambda
    - 18:11: Problems discussed when the initialization is more complex
    - 18:44: Challenges highlighted with two-step initialization and potential undefined behavior
    - 19:19: Problems noted when the object does not have a default constructor
    - 19:31: Discussed issues when the object is const and can only be initialized once
    - 20:08: Suggested solutions include ternary expressions and separate initialization functions
    - 21:10: Introduced the solution of immediately invoked Lambdas for these scenarios
    - 21:30: Highlighted the use of this idiom for perfect forwarding scenarios such as in place back, make shared, etc
    - 22:23: Discussed readability concerns with the Lambda and offered the use of std::invoke as a solution
    *Never Again*
    - 22:59: Start talking about learning from Daisy Holman's talk on "What you can learn from being too cute". Discussing a task where you want a snippet of code to run only once.
    - 23:26: Example given using a struct and constructor. The *code should only run the first time* an object is initialized.
    - 23:38: Discusses a use case where this method is applicable - when class behavior depends on CPU instruction support.
    - 24:21: Suggests wrapping the code in a lambda, which can be invoked to return a value only once and assign it to a static object.
    - 24:59: Discusses how the C++11 guarantee of static object initialization prevents multiple initializations.
    - 25:17: Notes *thread safety* of this approach, where initialization is safe even across multiple threads.
    - 25:48: Mentions small runtime overhead for checks ensuring code doesn't run more than once.
    - 26:18: Compares this hand-written solution to the standard library's std::call_once, claiming it's more performant.
    *Generic Lambda*
    - 26:25: Moves on to discuss C++14 features, particularly generic lambdas.
    - 26:41: Explains that using auto in lambda function parameters lets the compiler deduce the type.
    - 27:45: Elaborates that for a generic lambda, the compiler creates a function template for the call operator.
    - 28:16: Notes that generic lambdas with no state still provide an implicit conversion to function pointer.
    - 28:29: Discusses how generic lambdas can be passed as parameters to legacy calls expecting function pointers.
    - 28:55: Points out limitation of generic lambdas when used with a plus operator due to type ambiguity.
    - 29:13: Discusses perfect forwarding and variadic templates support in generic lambdas.
    - 30:03: Demonstrates ease of passing lambdas into other lambdas due to auto syntax.
    *Variable Template*
    - 30:43: Discusses variable templates as a feature in C++14.
    - 31:07: Breaks down a code example showing a lambda as a variable template with accessible template parameters.
    - 32:09: Explains that variable templates have two types of template parameters: those of the variable and those of the call operator.
    - 32:59: Provides a specific example from Bjorn Fahller where the technique is used for a time conversion function.
    *Init Capture*
    - 38:16: Discusses init capture, a feature introduced in C++14 that allows variables to be initialized within the lambda capture.
    - 38:57: Shows how init capture allows for the capture of variables such as unique pointers that would otherwise not be possible to capture by value.
    - 39:39: Discusses use case of init capture for optimization, demonstrating how it can be used to efficiently pre-calculate a value in a find_if operation.
    *Class Template Argument Deduction*
    - 41:18: Introduction to features introduced in CSR17 relating to Lambdas.
    - 41:30: Lambdas can now be const expert, allowing them to be executed at compile time.
    - 41:41: Introduction to class template argument deduction (CTAD) in CSR17.
    - 41:54: CTAD allows you to use templates without having to spell out their parameters.
    - 42:22: CTAD can save a lot of typing and make complicated examples easier.
    - 42:41: CTAD doesn't directly relate to Lambdas, but enables a technique for creating callable objects acting as *overload sets* (interesting).
    - 43:01: Callable object example: if given an integer, it calls an integer overload; if given a float, it calls a float overload.
    - 43:32: You can inherit from Lambdas since they generate a closure type (a Class Type).
    - 44:56: Overload is an aggregate as it has no user-defined Constructors or private members.
    - 45:16: In C++17, a deduction guide is needed for aggregate initialization, but in C++20 the compiler does it automatically.
    *C20 Lambda Changes*
    - 46:40: Introduction to features introduced in C++20 relating to Lambdas.
    - 46:48: New features include lambdas capturing structured bindings and parameter packs, and being constable.
    - 47:00: Lambdas can be called at compile time if called with a compile time constant, but will error if called with a runtime variable.
    - 47:08: Templated Lambdas allow for constraints to be applied to types and meta programming on the Lambda.
    - 47:36: Lambdas are now allowed in unevaluated contexts and can be default constructed and assigned.
    - 47:49: In C++20, Lambdas can be a data member of a class.
    - 49:33: Unique Type Generator idiom can be used to generate new types.
    - 53:23: Introduction to features expected in C++23.
    *C23 Deducing*
    - 53:29: Introduction to deducing this feature in C++23.
    - 55:50: Deducing this feature allows for recursive lambdas, reducing the need to write multiple overloads.
    - 59:02: Recursive lambda example using a binary tree variant.
    *Tree Traversal*
    - 59:22: Implementing tree traversal using a lambda overload pattern.
    - 1:00:07: With deducing this feature, lambda can call itself recursively using the fully derived type.
    - 1:00:33: There are various use cases for recursive lambdas.
    Disclaimer: I utilized gpt4-8k 0613 to condense the video transcript
    into a summary.

  • @matt42hughes
    @matt42hughes 2 роки тому +35

    I think you've definitely taught everyone (from beginners to experts) at least one thing today. Lambdas are so flexible.... thanks for the presentation!

  • @sirnawaz
    @sirnawaz 2 роки тому +4

    37:00. In other words, what you need is "partial application of std::chrono::duration_cast, applying only the first template argument". Interesting example!

  • @ask43242flight
    @ask43242flight 2 роки тому +2

    This is the BEST tutorial on lambda.

  • @Daniel-rk3vf
    @Daniel-rk3vf Рік тому

    Excellent, useful, informational and well-paced presentation. Well done Timur!

  • @dexterman6361
    @dexterman6361 2 роки тому +7

    Damn I didn't know so many things. This is an AMAZING talk, thank you! I did learn A LOT!

  • @OlzhasA
    @OlzhasA 2 роки тому +4

    16:16 is that a typo with const float f = 42.0f; instead of const float i = 42.0f;?

    • @hansolsson874
      @hansolsson874 2 роки тому

      Also saw that, and given that the lambda is called f it must be.

  • @ЯсенПень-ф9л
    @ЯсенПень-ф9л 2 роки тому +6

    It seems to me that to demonstrate the power of Immediately Invoked Lambda Expressions, it could be taken as an example of the initialization of a class member in the constructor initialization list

  • @davnmu
    @davnmu Рік тому +1

    Very insightful, I didnt know lambdas could take lambdas as arguments and return lambdas. The is something I need to revisit to get my head round, thanks.

  • @TheMyHalo
    @TheMyHalo 2 роки тому

    Liked your previous talks, glad to see new one this year

  • @simonherrera9373
    @simonherrera9373 2 місяці тому

    Mind blowing presentation.

  • @mikekaganski
    @mikekaganski 2 роки тому +2

    Initializing a function-local static using a lambda also allows to have a local and thread-safe complex initialization (as another reason to use lambdas in initialization, instead of assigning after creation)

  • @ultradude5410
    @ultradude5410 Рік тому

    22:45 I honestly don’t like using invoke for IILE, since in C++17, invoke is not constexpr. It didn’t get constexpr until C++20.

  • @OlliS71
    @OlliS71 Рік тому +2

    I can recommend the book "C++ Lambda Story".

  • @natedoggstyle
    @natedoggstyle 2 роки тому +1

    Awesome talk!

  • @guofuzhong4102
    @guofuzhong4102 Рік тому

    amazing video for C++ Lambda Idioms!

  • @Swedishnbkongu
    @Swedishnbkongu 2 роки тому +2

    Someone has got to share the link to whatever the last question/comment was talking about with implementing std tuple

  • @JohnDlugosz
    @JohnDlugosz 2 роки тому +12

    For Immediately Invoked Lambda Expressions, I don't just write () at the end of it. Rather, I include a comment inside the parens: (/*IILE*/)
    That makes it stand out.
    But if I'm feeling mean, I'll write: (/*)(*/)
    which arguably does make it stand out and draw attention to it, so is good code.

  • @JohnDlugosz
    @JohnDlugosz 2 роки тому +2

    Slide 153 (about 53:15): How does generating unique _types_ allow you to not have to come up with unique names for global variables?
    If you write: X v1,v2;
    then v1 and v2 are of different types, but you still named the variables v1 and v2! How does having this template X allow you to write unique global variables without having to come up with names for them?

    • @ХузинТимур
      @ХузинТимур 2 роки тому +1

      I think, `X v1, v2;` would lead to having them same type.
      As for question... You probably can make a template class which contains static variables with provided type, and you can supply this different `X` types to that class as template parameter.

    • @TheFerdi265
      @TheFerdi265 Рік тому

      you can use a variable template:
      template
      T unique;
      struct noisy { noisy() { std::cout

  • @PUZO37RS
    @PUZO37RS Рік тому

    Really cool talk! Very informative! Thanks!

  • @schobihh2703
    @schobihh2703 2 роки тому +8

    Do you need a PhD to program in C++ nowadays?

    • @khatdubell
      @khatdubell 2 роки тому

      no

    • @llothar68
      @llothar68 Рік тому +1

      @@khatdubell only 20 years of experience

  • @maximkosheleff
    @maximkosheleff 2 роки тому +6

    Camera tracking looks like presentation was on a cruise ship during storm

    • @Argletrough
      @Argletrough Рік тому

      Looks like it might be using an AI system. Think I saw Nvidia showing it off.

  • @hordi1ful
    @hordi1ful 2 роки тому

    Thank you, many interesting examples.

  • @johnstorm589
    @johnstorm589 2 роки тому +1

    Mind bending

  • @user-ge2vc3rl1n
    @user-ge2vc3rl1n Рік тому

    No color highlight in the code makes me very sad

  • @raymondchen2257
    @raymondchen2257 2 роки тому

    iirc some compilers do optimization for []{} that different []{} wil be viewed as same type.

  • @tacticalassaultanteater9678
    @tacticalassaultanteater9678 2 роки тому

    Why not just have a std fix point combinator for recursion? Explicitly specifying the point we're calling back to sounds less error-prone than calling whatever wrapper the user is holding.

  • @atharkhan7566
    @atharkhan7566 2 роки тому

    Good presentation...

  • @betelgeuse3287
    @betelgeuse3287 2 роки тому

    Are slides for this talk available ?

  • @Bbdu75yg
    @Bbdu75yg Рік тому

    Amazing❤

  • @think2086
    @think2086 2 роки тому +4

    C++ be crazy yall.

  • @dacresni
    @dacresni 2 роки тому

    where can i download these slides?

  • @yash1152
    @yash1152 2 роки тому

    0:07 JetBrains woah, Kotlin rocks yeay!!

  • @zxxvcc
    @zxxvcc Рік тому

    We use the unary plus trick in production code 😎

  • @jaybee9054
    @jaybee9054 Рік тому

    Good stuff! And please add Xcode project file support to CLion soon... 😜

  • @khatdubell
    @khatdubell 2 роки тому +2

    "We come to our first trick, do not use this in production"
    Me, already using this in production: 👀

    • @hannesw928
      @hannesw928 2 роки тому

      I know the feeling …

  • @dojcubic
    @dojcubic 2 роки тому

    slide 47: "f" is used as the variable name for the float and for the lambda. Should be corrected.

  • @chidude16
    @chidude16 2 роки тому

    very good.

  • @ABaumstumpf
    @ABaumstumpf 2 роки тому

    Deducing this - strangely enough i only used it once and that was with volatile :P

  • @Gennys
    @Gennys 2 роки тому

    I really don't like the square bracket syntax, but I've been getting into lambdas and they are so nice as they force you into thinking about problems and solutions differently.

  • @siyachieng666
    @siyachieng666 2 роки тому +2

    Thanks, btw C++ get more and more tricks every 3 years🤣

  • @dexio85
    @dexio85 Рік тому

    "Please don't do that in production code" - WHY? Speker didn't explain anything here.

  • @neshkeev
    @neshkeev Рік тому

    Deducing `this` is beyond good and evil, the syntax is so weird)

  • @phenixwutao
    @phenixwutao 2 роки тому

    it looks similar to C# delegates, I would say.

  • @francisgrizzlysmit4715
    @francisgrizzlysmit4715 2 роки тому

    a very weird way of saying hello world 😁🤠

  • @stefanusayudha1853
    @stefanusayudha1853 2 роки тому

    the lamda calculus implementer be like: he guys, you think c is hard? check what i've done to it..

  • @Tresorthas
    @Tresorthas 2 роки тому +1

    But we still cannot capture 'that'...

  • @enricomariadeangelis2130
    @enricomariadeangelis2130 5 місяців тому

    Regarding, 37:13, there's BOOST_HOF_LIFT.
    Regarding 43:20, lamba idiom 6, there's boost::hana::overload, why noboday knows? Boost.Hana is great! :D

  • @tahitinguyen4822
    @tahitinguyen4822 Рік тому +1

    The talk get complicated really really quickly

  • @nortonp240
    @nortonp240 2 роки тому +3

    That is rely not cool, we are adding so many obscure way of coding stuff in c++ without removing old stuff, this is going nowhere

    • @davecaloway1993
      @davecaloway1993 2 роки тому

      What old stuff should be removed, exactly?

    • @origamitraveler7425
      @origamitraveler7425 2 роки тому +1

      nah this is great

    • @nortonp240
      @nortonp240 2 роки тому +1

      ​@@davecaloway1993 Maybe not removed all together but pushed in a legacy namespace,
      just some example:
      - We added ranges without removing begin/end based algorithms.
      - The preprocessor for sure (just need a constexpr way to stringify a var name an minor other things)
      - Its a bold thing to think but i would like to remove new and delete (the fact that mk unique was not there in C++ 11 is a sing that they were not taking seriously the smart pointer model)
      - Since optional and reference wrappers where added, we never need to use a raw pointer for anything else than for C interfaces (man it sucks to have to type std::optional)
      Go see a C++ introduction course and you will see 80% C.
      I see all the new developers learning in old code bases making all the same mistakes everybody made, it should be hard to code baldy. Today it is the opposite.
      Just using smart pointers is alien to maybe 60% of C++ devs, and we are there adding obscure stuff to the language without mending it of its technical debt.

    • @nortonp240
      @nortonp240 2 роки тому

      @@origamitraveler7425 people don't even know how to use lambdas
      templates make theme shiver

    • @dnaphysics
      @dnaphysics 2 роки тому

      C++ = enough power to easily be humanly incomprehensible

  • @eyesopen6110
    @eyesopen6110 Рік тому

    lambdas are crap. All of a sudden everything is a f_k'n lambda and its a lazy mess.

  • @rivendzi
    @rivendzi Рік тому

    Fantastic talk!