Standard algorithm to operate on adjacent elements

361 Views Asked by At

std::adjacent_find looks for the first two consecutive elements that satisfies the given predicate. I am looking for other algorithms that also has a predicate that takes the (previous, current) pair. This is useful for rendering polygons, computing numerical quadrature based on sample data etc.

In addition to std::adjacent_find there is std::adjacent_difference, which can be used to implement a one-dimensional filter, but is not useful if you only want the sum of op(previous, current).

Can such functions be emulated with some kind of view from std::ranges?

2

There are 2 best solutions below

2
MSalters On BEST ANSWER

There's no special function for this, because you can just call the binary transform std::transform(c.begin(), std::prev(c.end()), std::next(c.begin()), op). This works on the overlapping ranges [c.begin(), c.end()-1] and [c.begin()+1, c.end()].

Similarly, other operations that take two input ranges can work on two overlapping ranges as long as they don't modify the inputs.

This can also work with greater differences than +/-1. It should be noted that this does not work on input iterators - they're one-pass.

0
Adam A.C. Fox On

Since C++23 there're std::views::adjacent<N> that reinterprets a given range in terms of a view of N-tuples. Which is a powerful tool with structured binding allowing you traverse the range with named class fields. E.g. if N==2,

std::vector<T> v{...};
for (auto [former, latter]: v|adjacent<2>){...}

And obviously the corresponding std::views::adjacent_transform<N> view is provided as well, which will return view of results of applying the given N-nary function to every N-tuple:

for (auto i: v|adjacent_transform<3>(
[](T a, T b, T c) { return /*...*/; })) {...}