Zach Clayburn
Zach Clayburn

Reputation: 95

How to use C++ 20 range views with a user defined type

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

Upvotes: 1

Views: 1237

Answers (1)

Nicol Bolas
Nicol Bolas

Reputation: 474086

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

Upvotes: 0

Related Questions