C++ Weekly - Ep 428 - C++23's Coroutine Support: std::generator

Поділитися
Вставка
  • Опубліковано 12 тра 2024
  • ☟☟ Awesome T-Shirts! Sponsors! Books! ☟☟
    Upcoming Workshop: Understanding Object Lifetime, C++ On Sea, July 2, 2024
    ► cpponsea.uk/2024/sessions/und...
    Upcoming Workshop: C++ Best Practices, NDC TechTown, Sept 9-10, 2024
    ► ndctechtown.com/workshops/c-b...
    CLion is a cross-platform JetBrains IDE for C and C++ with:
    - A smart C and C++ editor to navigate and maintain your code base productively.
    - Code analysis with quick-fixes to identify and fix bugs and style inconsistencies.
    - An integrated debugger - along with other essential tools from the ecosystem - available
    straight out of the box.
    - And much more!
    jb.gg/clion_ide code: CppWeeklyCLion
    Episode details: github.com/lefticus/cpp_weekl...
    T-SHIRTS AVAILABLE!
    ► The best C++ T-Shirts anywhere! my-store-d16a2f.creator-sprin...
    WANT MORE JASON?
    ► My Training Classes: emptycrate.com/training.html
    ► Follow me on twitter: / lefticus
    SUPPORT THE CHANNEL
    ► Patreon: / lefticus
    ► Github Sponsors: github.com/sponsors/lefticus
    ► Paypal Donation: www.paypal.com/donate/?hosted...
    GET INVOLVED
    ► Video Idea List: github.com/lefticus/cpp_weekl...
    JASON'S BOOKS
    ► C++23 Best Practices
    Leanpub Ebook: leanpub.com/cpp23_best_practi...
    ► C++ Best Practices
    Amazon Paperback: amzn.to/3wpAU3Z
    Leanpub Ebook: leanpub.com/cppbestpractices
    JASON'S PUZZLE BOOKS
    ► Object Lifetime Puzzlers Book 1
    Amazon Paperback: amzn.to/3g6Ervj
    Leanpub Ebook: leanpub.com/objectlifetimepuz...
    ► Object Lifetime Puzzlers Book 2
    Amazon Paperback: amzn.to/3whdUDU
    Leanpub Ebook: leanpub.com/objectlifetimepuz...
    ► Object Lifetime Puzzlers Book 3
    Leanpub Ebook: leanpub.com/objectlifetimepuz...
    ► Copy and Reference Puzzlers Book 1
    Amazon Paperback: amzn.to/3g7ZVb9
    Leanpub Ebook: leanpub.com/copyandreferencep...
    ► Copy and Reference Puzzlers Book 2
    Amazon Paperback: amzn.to/3X1LOIx
    Leanpub Ebook: leanpub.com/copyandreferencep...
    ► Copy and Reference Puzzlers Book 3
    Leanpub Ebook: leanpub.com/copyandreferencep...
    ► OpCode Puzzlers Book 1
    Amazon Paperback: amzn.to/3KCNJg6
    Leanpub Ebook: leanpub.com/opcodepuzzlers_book1
    RECOMMENDED BOOKS
    ► Bjarne Stroustrup's A Tour of C++ (now with C++20/23!): amzn.to/3X4Wypr
    AWESOME PROJECTS
    ► The C++ Starter Project - Gets you started with Best Practices Quickly - github.com/cpp-best-practices...
    ► C++ Best Practices Forkable Coding Standards - github.com/cpp-best-practices...
    O'Reilly VIDEOS
    ► Inheritance and Polymorphism in C++ - www.oreilly.com/library/view/...
    ► Learning C++ Best Practices - www.oreilly.com/library/view/...
  • Наука та технологія

КОМЕНТАРІ • 38

  • @ohwow2074
    @ohwow2074 27 днів тому +7

    Imagine this combined with the upcoming networking library! I don't even know what exactly is possible.

    • @KulaGGin
      @KulaGGin 27 днів тому +1

      I never liked this approach. The default procedural approach working together with OOP is much easier to understand than this functional programming approach.
      I've seen even people who are proponents of functional programming admit that the default procedural + OOP is much easier to understand than this.

  • @sjswitzer1
    @sjswitzer1 27 днів тому +18

    Very nice to see generators landing but I’m not convinced that std::exchange is contributing to the transparency or readability of this code

    • @__Brandon__
      @__Brandon__ 26 днів тому +7

      He did say tersest way possible

    • @cppweekly
      @cppweekly  26 днів тому +3

      That is what I said. Also, exchange is super helpful when you need it, so learning how to read it is super helpful.

    • @wojciechrazik
      @wojciechrazik 25 днів тому

      I think that our brains get use to unusual syntax. When you learn C++ - lambdas look terrible. After a while you get use to it. The more you see std::exchange, it will be more natural.

  • @darkmagic543
    @darkmagic543 27 днів тому

    Awesome, I hope other compilers will implement it soon as well so that people can start adapting it

  • @LesleyLai
    @LesleyLai 23 дні тому +1

    I know ranges are cool and offer many more functionalities (constexpr, potential random access, and so on). But it is such *much* easier to actually author generators than either traditional iterators or ranges.

  • @bryce.ferenczi
    @bryce.ferenczi 27 днів тому +4

    Going to have to get out of the habit of reaching for std::cout and use std::println instead.
    Its also interesting how much code hello world with std::println produces with -O(2/3), maybe an episode on why that is the case would be interesting. At compile time it should be known I'm printing a basic string and not using any formatting and remove all the formatting boilerplate etc.

    • @cppweekly
      @cppweekly  26 днів тому +1

      This is why I'm tending to not use it in C++ Weekly. It's unfortunately slow to compile and obfuscates the binary.
      I hope they make it better soon

  • @von_nobody
    @von_nobody 27 днів тому +6

    I would make some observation, code like `for (auto i : foo() | bar())` was tricky in older C++ as value returned from `foo()` could be destroyed as lifetime was bound only to `foo() | bar()` expression, but recent C++ fix it and make that temps in range `for` live as long this `for` is in scope.

    • @testtest-qm7cj
      @testtest-qm7cj 26 днів тому

      Are you referring to C++23 'Extending the lifetime of temporaries in range-based for loop initializer' ?

    • @von_nobody
      @von_nobody 26 днів тому

      @@testtest-qm7cj Yes, this, small change but how much it improve life

  • @alexandrebustico9691
    @alexandrebustico9691 27 днів тому +2

    also compile with just released gcc 14.1

  • @mrlumps8711
    @mrlumps8711 27 днів тому +1

    The difference in assembly output is quite large. I imagine the optimization maniacs have not had their fun yet with std generator

  • @user-ph6ct7ug8z
    @user-ph6ct7ug8z 25 днів тому +1

    std::generator allocates. The lambda function in the previous video returns a very weird type, since it is auto. Is there a way to have the best of both: a generator class/template, to which I tell to use a certain amount of memory to work with on the stack. kind of like the new flatmaps with arrays. e.g. std::generator ?

    • @Evan490BC
      @Evan490BC 19 днів тому +1

      It doesn't return "a very weird type", actually. It just returns an _unknown_ type. You just have to remember that lambdas are just anonymous function classes.

    • @cppweekly
      @cppweekly  11 днів тому

      Nothing built in, but it might be possible to construct something.

  • @toast_on_toast1270
    @toast_on_toast1270 27 днів тому +1

    I'm a C++ beginner/intermediate (~3 years experience, 2 of which on the job (take from that what you will)), and it's my only language so far.
    I gotta say, it seems like the perfect time to be getting deeper into it: in the back of my mind, I've had "I must sometime learn about coroutines" - now I have the fancy new features to do it!
    I am starting to take learning this language more seriously and I feel like your videos are gonna help me learn fast.

  • @Nobody1707
    @Nobody1707 27 днів тому +1

    -Fanalyzer does not like std::generator one bit.
    Also, here's a version of fib() with no UB that stops after the addition overflows:
    constexpr int wrapping_add(int a, int b) noexcept {
    return static_cast(a) + static_cast(b);
    }
    std::generator fib() {
    int i = 0;
    int j = 1;
    while (true) {
    co_yield (i = std::exchange(j, wrapping_add(i, j)));
    if (j < i) {
    break;
    }
    }
    }

    • @Nobody1707
      @Nobody1707 27 днів тому

      And if you add a co_yield 0; before the loop it'll yield the classical version of the sequence.

    • @Nobody1707
      @Nobody1707 27 днів тому +1

      Actually, I made this too complicated, just yield I before you compute the next number in the sequence:
      std::generator fib() {
      int i = 0;
      int j = 1;
      while (i >= 0) {
      co_yield i;
      i = std::exchange(j, wrapping_add(i, j));
      }
      }

    • @driedurchin
      @driedurchin 27 днів тому

      Don’t you need a return outside the loop if you’re gonna break?

    • @Nobody1707
      @Nobody1707 27 днів тому

      @@driedurchin Nope. The generator stops yielding values when it reaches the end of the function. I think it returns some sort of stop token when you do that, so that loops over the generator know that you're done.

    • @driedurchin
      @driedurchin 26 днів тому

      @@Nobody1707 So it is different from a regular function in that control flow analysis doesn't care that you reach the end of a non-void function?

  • @colinkennedy
    @colinkennedy 26 днів тому +1

    Or you could write a for loop and reduce the generated assembly from 338 lines of unreadable asm to 30 lines of pretty readable asm. Probably faster too, though quick-bench doesn't support GCC 14.1+ so I wasn't able to verify.
    1. Copy to godbolt
    2. Flip #if 1 to #if 0
    3. See the assembly reduce by 90%
    ```
    #if 1
    #include
    #include
    #include // std::exchange
    #include
    std::generator fib()
    {
    int i = 0;
    int j = 1;
    while (true)
    {
    co_yield i = std::exchange(j, i + j);
    }
    }
    int main()
    {
    for (const auto i: fib() | std::views::take(20))
    {
    std::cout

    • @cppweekly
      @cppweekly  11 днів тому

      Yes, probably much faster for this simple use case to not use std::generator. ua-cam.com/video/F37h3FuA8kM/v-deo.html

  • @literallynull
    @literallynull 27 днів тому +1

    What are the good use cases of coroutines? Where can I learn more about them? Maybe .pdf book or something

    • @TsvetanDimitrov1976
      @TsvetanDimitrov1976 27 днів тому

      I think Donald Knuth's The Art of Computer Programming is probably the best known motivation for the need for coroutines, although there surely are more modern books

    • @truesoundwave
      @truesoundwave 27 днів тому +1

      Iterative Tasking.
      Sometimes, you don't want to do all of your work up front. You want to do it in chunks.
      Writing code to support something like this is an absolute pain once it gets complicated.

  • @mjKlaim
    @mjKlaim 27 днів тому

    Yay for coroutines!
    I've exploited to death `std::generator` in ways that works surprisingly through the years, it's very interesting what you can do with that as soon as you understand how to manipulate manually the iterator from `begin()`

  • @alskidan
    @alskidan 27 днів тому

    The infinite loop is UB, isn’t it?

    • @Nobody1707
      @Nobody1707 27 днів тому +2

      I think not, because co_yield is a side effect. Also, I think C++26 makes while(true) { } defined anyway.

    • @arthapz
      @arthapz 27 днів тому

      @@Nobody1707 yes but not while(true) { int i = 0; } afaik

    • @Nobody1707
      @Nobody1707 27 днів тому

      @@arthapz No, C++26 I believe is aligning the rules to be closer to C's. If the loop condition is the literal true then the infinite loop is defined behavior. Other forms of infinite loops will still not be.

  • @anon_y_mousse
    @anon_y_mousse 8 днів тому

    I still say that the functional paradigm seeping into C++ is a bad thing. It's ugly, harder to understand than its procedural counterpart and requires much more compiler support to optimize it than the alternative. If anyone has to ask why requiring more compiler support is a bad thing, consider that one of the chief complaints against Rust is the compilation speed and how this would make C++'s compilation speed worse than it already is and put it more on par with Rust. Consider also that the harder a language is to implement that the fewer vendors we'll have. Perhaps that doesn't matter to anyone and they're fine with only having three vendors seriously competing, but monoculture in nature is a bad thing just as it is here. You may not see the ill effects today, but transitioning in the future will be harder still than it already is. Think of all the legacy codebases out there, especially the ones that are held together with duct tape and chewing gum.