C++ Weekly - Ep 342 - C++20's Ranges: A Quick Start

Sdílet
Vložit
  • čas přidán 30. 05. 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...
    Ep 340 - Finally! A Simple String Split in C++! - • C++ Weekly - Ep 340 - ...
    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/...
  • Věda a technologie

Komentáře • 54

  • @vesk4000
    @vesk4000 Před měsícem +1

    This is such a cool video! Very useful and to the point! Exactly whay I needed!

  • @mjKlaim
    @mjKlaim Před rokem +9

    I remember catching such kind of bugs (from the beginning) in a bunch of unit tests simply by running the test with visual studio Debug mode which also adds iterator checks.

  • @victotronics
    @victotronics Před rokem +16

    Very nice tutorial. So with that last example you basically have the python "enumerate" iterator. How hard would "zip" be? Is that going to be in 23?

    • @cppweekly
      @cppweekly  Před rokem +13

      Zip is in 23, yes

    • @yogthemuskrat
      @yogthemuskrat Před rokem

      There is actually an `enumerate` adapter on Range-V3, btw.

    • @StephenWarren
      @StephenWarren Před rokem +3

      See also std::ranges::views::iota, std::ranges::iota_view. iterate_with_index() is basically zip with iota.

  • @KennyMinigun
    @KennyMinigun Před rokem +27

    That std::ranges::views is quite a mouthful. I just looked up on cppreference, and bless the creators there is an alias namespace std::views = std::ranges::views.

    • @TheMR-777
      @TheMR-777 Před rokem +1

      I always define an alias of myself, before using ranges,
      namespace rg = std::ranges;
      namespace vs = rg::views;
      In this way, you can also easily switch b/w std::ranges and range-v3.

    • @Voy2378
      @Voy2378 Před rokem +4

      @@TheMR-777 I use sv and sr but yeah full namespaces are a bad joke

  • @oschonrock
    @oschonrock Před rokem +3

    For the record, after playing around on CE, it turns out that gcc 12.2 with libstdc++ can run the above code (trunk is not required) and clang trunk with libc++ can also run it. So some progress!

  • @DiegoHavenstein
    @DiegoHavenstein Před rokem +1

    The transform + make index example is something I tried out recently, but used zip(iota(0), vec) instead. Zip has a special case when 2 args are passed so a std::pair is returned just as in the example from the video

  • @sheeftz
    @sheeftz Před rokem +10

    7:33 You used a lamda with a side effect . There is no explicit requirement for the function parameter in ranges::transform not to have side effects, but are you sure that it means it guarantees to call the transformation function object in the expected order and once per object? There is no explicit guarantees of that.

    • @yogthemuskrat
      @yogthemuskrat Před rokem +4

      There is no such guarantee. Even more - there is a well known "filter | transform" problem when transform gets called more times that you'd expect.

    • @sheeftz
      @sheeftz Před rokem +5

      @@yogthemuskrat Well, then it's broken in the most dangerous way things can be broken in c++. He'd better fix this before people start thinking that lambdas with side effect in views is a smart thing to do.

    • @cristian-si1gb
      @cristian-si1gb Před rokem

      @@sheeftz Actually, this was always a problem with STL algorithms. See "std::find() is Broken!" by Sean Parent czcams.com/video/2FAi2mNYjFA/video.html&ab_channel=CppCon

    • @danrobinson2866
      @danrobinson2866 Před 3 měsíci +1

      I tried the following and expected to see the index values start at 5, that was not the case.
      for(const auto &[index, elem] : get_data()| std::ranges::views::transform(make_index) | std::ranges::views::drop(5)) {
      fmt::print("{}: {}
      ", index, elem);
      }

  • @oschonrock
    @oschonrock Před rokem +5

    Doesn't number 3) have lifetime issues as well? Because the ranged for is transformed into a begin() call and then the loop and by then the temporary is gone? Or was that a different scenario, or is now fixed?? Or does the drop view actually save us here, because it extends the lifetime of the temporary vector until we have finished iterating it - because it's lazy. ?

    • @cristian-si1gb
      @cristian-si1gb Před rokem +4

      It's safe, the lifetime of the owning_view is extended by __range and begin/end are called on it.
      auto && __range = range-expression ;
      auto __begin = begin-expr ;
      auto __end = end-expr ;
      for ( ; __begin != __end; ++__begin)
      {
      range-declaration = *__begin;
      loop-statement
      }

    • @oschonrock
      @oschonrock Před rokem

      @@cristian-si1gb Thanks. I guess I had that "electric tingling alert" as soon as I saw the "2 step temporary", which is normally what produces this problem.
      But I guess these views are designed to capture the thing in front of the pipe in some kind of internal reference (that's the "owning" part?), and then, as you say, the view becomes a "one step temporary" which is safely lifetime extended by auto&& __range reference.
      Is that right?

    • @cristian-si1gb
      @cristian-si1gb Před rokem

      @@oschonrock All views will by default apply std::views::all on the range they're based on. It's a bit too much to explain in depth here, Tristan Brindle just had a talk explaining why and how this works: czcams.com/video/L0bhZp6HMDM/video.html&ab_channel=CppNorth

  • @VictorHugoVideos
    @VictorHugoVideos Před rokem

    The make_index trick was something that I've always wondered why it didn't existed already.

  • @ChristianBrugger
    @ChristianBrugger Před rokem

    I find ranges very exciting. Two problems I struggled with adopting it in my application:
    * compile times exploding, up to 10 seconds for a single cpp file in both clang and MSVC
    * very inefficient code generation for some Code
    I would love to get more deeper insights into this and waiting for someone to cover it. I know sone of it is a quality of implementation problem, but I don't think fully. Some is me using the library in a non optimal way.

    • @cppweekly
      @cppweekly  Před rokem +1

      Ranges are complex, so I'm honestly not surprised. But I have not measured it myself. I think in many cases the expressiveness will outweigh the costs.

  • @alexbalrus
    @alexbalrus Před rokem

    На первый взгляд сложные конструкции. Почти ничего не понял) Кто-нибудь уже оценил - ranges это действительно замена stl? Есть в них значительная польза?

  • @hammad7829
    @hammad7829 Před 22 dny

    how do you type so fast??

  • @DrPastah
    @DrPastah Před rokem

    std::range isn't a thing for C++14 is it?

    • @ChrisCarlos64
      @ChrisCarlos64 Před rokem +3

      It came with C++20, so no it isn't for C++14

    • @yogthemuskrat
      @yogthemuskrat Před rokem +2

      There is range-v3 for that (older versions).

  • @c0d3_m0nk3y
    @c0d3_m0nk3y Před rokem +1

    This is basically the same as LINQ in C#, isn't it?

    • @OperationDarkside
      @OperationDarkside Před rokem +1

      Correct me if I'm wrong, but LINQ was supposed to look like SQL but inside C# code. I don't know the C# equivalent, but Java has the streams API, that is kind of similar.

    • @c0d3_m0nk3y
      @c0d3_m0nk3y Před rokem +1

      C# LINQ:
      data
      .Where(a => a % 2 == 0)
      .Select(a => a * a)
      .Take(2);
      C++20 ranges:
      data
      | filter([](const int& a) { return a % 2 == 0; )
      | transform([](const int& a) { return a * a; })
      | take(2);

    • @keshkek
      @keshkek Před rokem

      @@c0d3_m0nk3y if you want to use sql like code in c++ you should write DSL which will detect errors etc oni compile time instead of using common code

  • @PaulMetalhero
    @PaulMetalhero Před rokem

    The scripting engine, please!

    • @cppweekly
      @cppweekly  Před rokem +1

      If only I could drop my contract work and have all of my time to spend on these things!

  • @anon_y_mousse
    @anon_y_mousse Před rokem +3

    I know it'll never happen, but C++ needs a slice operator. What you just showed with std::ranges::views makes me want to barf.

    • @valizeth4073
      @valizeth4073 Před rokem

      I mean, its not far from many other languages piping operator, like elixirs |>

  • @billynugget7102
    @billynugget7102 Před rokem +4

    Im not sure about everyone else but a simple for loop with an index (yes this feature does still exist) is much more understandable than what has been presented here. Despite it being more expressive (if you know what is going on) it continues the problem of polluting c++ with more special keywords and libraries that make it less and less accessible than the average enthusiast.
    “Idiots idolise complexity, a genius strives for simplicity”

    • @yogthemuskrat
      @yogthemuskrat Před rokem +3

      A raw loop is easier to understand when it is simple. But with every new condition (like, skip first element, reverse etc.) it gets messier and messier. And it gets not just harder to read but also much more error prone.
      View adapter on other hand make it easier to follow the "respect the layers of abstraction" principle - that is they strip away all the details of HOW you implement from WHAT you want to do.

    • @billynugget7102
      @billynugget7102 Před rokem +1

      @@yogthemuskrat bro if you can’t understand for(int i = 1; i

    • @yogthemuskrat
      @yogthemuskrat Před rokem +1

      @@billynugget7102 You should add a check, to ensure that container is not empty. A little thing, but it adds verbosity and breaks outside the loop itself.

    • @hstrauss2214
      @hstrauss2214 Před rokem +1

      A simple for loop with an index might be more understandable, but it is also more restrictive. Just change the vector in the example to a list, an it won't work any more. The presented solution is more general and therefore very much has its justification.

    • @billynugget7102
      @billynugget7102 Před rokem

      @@hstrauss2214 yeah you can justify it that wat but im saying becuase its so clunky many devs will opt for a more simple (and arguably less “expressive”) solution

  • @spjuanjoc
    @spjuanjoc Před rokem

    Just FYI, with fmt/ranges it should be possible to:
    //...
    #include
    //...
    fmt::print("{}", get_data() | std::ranges::views::drop(1));
    //...

  • @toRatnesh
    @toRatnesh Před rokem

    This is why sanitizer builds are helpful
    Compiling with sanitizer (-fsanitize=address) gives error for this
    auto result = std::all_of(get_data().begin(), get_data().end(), [](const int i){ return i < 5;});

    • @cppweekly
      @cppweekly  Před rokem

      Hmm... I definitely tested with asan and didn't get this error caught, must have used the wrong combination of compiler/tests

    • @toRatnesh
      @toRatnesh Před rokem

      I was using count_if and for_each instead of all_of and got sanitizer error, so I assumed behavior will be same for all_of but it has different behavior