Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
QStringView Diaries: Zero-Allocation String Splitting (kdab.com)
27 points by jcelerier on June 6, 2020 | hide | past | favorite | 5 comments


Hey that's pretty neat! It does feel a bit sad to vend a heap-allocating vector of string views when it's only used for iteration.

Definitely gonna do something similar for my own C++ toolkit. :)


This could simply be done as an iterator over a string. Why all the fancy schmancy C++ features?

EDIT: I'm starting to suspect it actually is just an iterator. So why not say that? Instead of mentioning the ranges library, coroutines, generators ...

EDIT: Ok, so ranges make sense. Coroutines still seem overkill to me though.


Ranges are a (start, end) pair of iterators that support begin/end -- think of them like a subset of containers that just provide access to the iterators over them. They also support the end iterator being a different type to the sstart iterator, supporting things like sentinel iterators (e.g. null pointer checks).

The next standard library supports using the standard algorithms with ranges, so you can say things like `std::sort(v)` instead of `std::sort(v.begin(), v.end())`.

IIUC, views are ranges that can adapt the results of the underlying object without changing the contents of that object, such as a lower-case view, or a reversed view. These work by doing the lower-case conversion on dereference, or swapping the increment/decrement operations.


> Coroutines still seem overkill to me though.

Coroutines are a fantastic way to implement ranges, in particular when you need runtime polymorphism over the way your range is implemented

e.g. they allow you to have for instance :

    class foo { 
       public: 
          virtual coroutine_range_type<int> get_foobar_list() const = 0;
    };


    class foo_using_vector : public foo {
      coroutine_range_type<int> get_list() const override { 
        for(int val : impl) 
          co_yield impl;
      }
      std::vector<int> impl;
    };


    class foo_using_some_fixed_list : public foo {
      coroutine_range_type<int> get_list() const override { 
         co_yield 1;
         co_yield 1;
         co_yield 2;
         co_yield 3; // or for instance getting something through some OS API, etc...
      }
    };
and then use that like you would use any container-like type, in range-based for-loops, in actual ranges...


Because a range is a pair of iterators and a coroutine is simply a convenient way to implement them.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: