C++ Lambda Idioms - Timur Doumler - CppCon 2022

Поділитися
Вставка
  • Опубліковано 21 лип 2024
  • cppcon.org/
    ---
    C++ Lambda Idioms - Timur Doumler - CppCon 2022
    github.com/CppCon/CppCon2022
    Ever since they were introduced in C++11, lambdas have been an essential language feature. Each subsequent standard added more functionality: we got generic lambdas and init captures in C++14, constexpr lambdas in C++17, default-construction and assignment, explicit template arguments and more in C++20, and even more possibilities are coming in the upcoming C++23 standard.
    In this talk, we are looking at various interesting things you can do with lambdas. Some of these are well-established, useful idioms; others are lesser known, surprising tricks. Have you ever inherited from a lambda? Can you think of three different ways to call a lambda recursively? Do you know what happens if we assign an immediately-invoked lambda expression to a static variable? If not, then this talk is for you.
    ---
    Timur Doumler
    Timur Doumler is the Developer Advocate for C++ tools at JetBrains and an active member of the ISO C++ standard committee. As a developer, he worked many years in the audio and music technology industry and co-founded the music tech startup Cradle. Timur is passionate about building inclusive communities, clean code, good tools, low latency, and the evolution of the C++ language.
    __
    Videos Filmed & Edited by Bash Films: www.BashFilms.com
    UA-cam Channel Managed by Digital Medium Ltd events.digital-medium.co.uk
    #cppcon #programming #lambda
  • Наука та технологія

КОМЕНТАРІ • 66

  • @matt42hughes
    @matt42hughes Рік тому +34

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

  • @wolpumba4099
    @wolpumba4099 8 місяців тому +6

    *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.

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

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

  • @sirnawaz
    @sirnawaz Рік тому +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 Рік тому +1

    This is the BEST tutorial on lambda.

  • @dexterman6361
    @dexterman6361 Рік тому +7

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

  • @Daniel-rk3vf
    @Daniel-rk3vf 8 місяців тому

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

  • @mikekaganski
    @mikekaganski Рік тому +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)

  • @davnmu
    @davnmu 11 місяців тому +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.

  • @user-nh5yb2uv4b
    @user-nh5yb2uv4b Рік тому +5

    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

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

    Really cool talk! Very informative! Thanks!

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

    amazing video for C++ Lambda Idioms!

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

    Thank you, many interesting examples.

  • @JohnDlugosz
    @JohnDlugosz Рік тому +11

    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.

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

    Awesome talk!

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

    Fantastic talk!

  • @OlliS71
    @OlliS71 8 місяців тому +1

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

  • @maximkosheleff
    @maximkosheleff Рік тому +5

    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.

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

    Good presentation...

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

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

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

    Amazing❤

  • @OlzhasA
    @OlzhasA Рік тому +4

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

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

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

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

    Are slides for this talk available ?

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

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

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

    Mind bending

  • @ultradude5410
    @ultradude5410 8 місяців тому

    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.

  • @think2086
    @think2086 Рік тому +3

    C++ be crazy yall.

  • @tacticalassaultanteater9678

    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.

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

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

  • @schobihh2703
    @schobihh2703 Рік тому +7

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

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

    very good.

  • @zxxvcc
    @zxxvcc 8 місяців тому

    We use the unary plus trick in production code 😎

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

    where can i download these slides?

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

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

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

    0:07 JetBrains woah, Kotlin rocks yeay!!

  • @user-ge2vc3rl1n
    @user-ge2vc3rl1n 8 місяців тому

    No color highlight in the code makes me very sad

  • @JohnDlugosz
    @JohnDlugosz Рік тому +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?

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

      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

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

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

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

    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

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

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

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

  • @dexio85
    @dexio85 9 місяців тому

    "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 Рік тому

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

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

    a very weird way of saying hello world 😁🤠

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

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

  • @enricomariadeangelis2130
    @enricomariadeangelis2130 18 днів тому

    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

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

    But we still cannot capture 'that'...

  • @tahitinguyen4822
    @tahitinguyen4822 8 місяців тому +1

    The talk get complicated really really quickly

  • @eyesopen6110
    @eyesopen6110 8 місяців тому

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

  • @nortonp240
    @nortonp240 Рік тому +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 Рік тому

      What old stuff should be removed, exactly?

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

      nah this is great

    • @nortonp240
      @nortonp240 Рік тому +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 Рік тому

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

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

      C++ = enough power to easily be humanly incomprehensible