0

At work I use a framework provided linked list for legacy reasons (I would change it if I could, but for the time being I can't). Also, this list must always exist on the heap, and accessed through a pointer. We have been able to extend it to provide an iterator, so it can be used in range based for loops and many standard algorithms, but I would also like to use C++ 20's new ranges library. This would allow for some useful constructs like

void functionUsingAwefulList(List* list) {
    for (auto item : list | filter(filterCondition) | transform(transformCondition)) {
        /* do things */
    }
}

but I can't get it to work. From my research on cpp reference, I see that std::ranges::begin and std::ranges::end are customization points, but I can't seem to overload it correctly. It seems like begin and end are both constexpr instances of some implementation defined class, but I don't know how to specify it for my specific type. How do I properly use the customization point?

Edit: There are already free begin() and end() functions that return iterators that allow this type to work in a range based for loop. I specifically want to know how to allow the use of the new ranges algorithms (that just take the container, not a begin and end iterator) and most of all the new range views (like filter and transform).

Zach Clayburn
  • 73
  • 1
  • 6
  • I suspect you're probably supposed to overload `std::begin` and `std::end`. – Mooing Duck Feb 09 '21 at 23:17
  • You provide member functions `begin()` and `end()` that return either a pair of iterators or an iterator and a sentinel. The code snippet as presented doesn't look right, `List*` shouldn't be a range, but maybe `List` is. – Barry Feb 09 '21 at 23:17
  • Does this answer your question? [How to make my custom type to work with "range-based for loops"?](https://stackoverflow.com/questions/8164567/how-to-make-my-custom-type-to-work-with-range-based-for-loops) – Mansoor Feb 09 '21 at 23:17

1 Answers1

0
list | filter(filterCondition)

That specifically is never going to work. Filtering and other view adaptors work on ranges, and a pointer (by itself) is not a range nor should it be.

If your List type is a range, and you have a pointer to one, you need to dereference it to apply filters to it: *list | filter(...).

Making your type into a range requires being able to query an iterator and a sentinel from it. That means you need to define a type that fits an appropriate iterator category (such as std::forward_range for a linked list). Then, you need to either add member begin/end functions to the type or add non-member begin/end functions accessible via ADL on the range type. They should return iterators (or a sentinel if you don't want to return an iterator on end).

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982