Search code examples
c++stlstl-algorithm

How to use std::lower_bound with a custom iterator?


I have a “two dimensional” data stored in a double array in a row major way. My data has 5 columns, time, x, y, z, and field.

  1. T1, x1, y1, z1, F1
  2. T2, x2, y2, z2, F2
  3. T3, x3, y3, z3, F3 …

This data is stored in a double 1D array in row major way. Like

double dataArray[] = { T1, x1, y1,z1,F1, T2,x2,y2,z2,F2, T3,x3,y3,z3,F3, ... };

Now I want to find the first row of the data for which time is equal to or greater than a given value T0. How can I use std::lower_bound to do this?

I guess that I need a ForwardIterator which returns every 5th element in that array but don't how to do that. Any help is appreciated.


Solution

  • You can write an iterator to do what you want pretty easily. I'm not aware of a drop-in that does just this.

    #include <algorithm>
    #include <iostream>
    
    template <typename T> struct SkipIt : public std::iterator<std::forward_iterator_tag, T> {
        SkipIt(T *t, unsigned skip) : elt(t), skip(skip) {}
        bool operator == (const SkipIt<T> &other) const { return elt == other.elt; }
        bool operator != (const SkipIt<T> &other) const { return elt != other.elt; }
         T *operator -> () const { return elt; }
        T &operator * () const { return *elt; }
        SkipIt &operator ++ () { elt += skip; return *this; }
        SkipIt operator ++ (int) { auto ret = *this; ++*this; return ret; }
        SkipIt operator + (int amt) const { auto ret = SkipIt(elt + amt * skip, skip); return ret; }
    
    private:
        unsigned skip;
        T *elt;
    };
    
    int main() {
        double test[] =
            { 0.1, 0.2, 0.3
            , 1.1, 1.2, 1.3
            , 2.1, 2.2, 2.3
            , 3.1, 3.2, 3.3
            };
        auto begin = SkipIt<double>(test, 3);
        auto end = begin + 4;
        auto res = std::lower_bound(begin, end, 2.0);
        if (res == end) {
            std::cout << "Lower bound not found\n";
        } else {
            std::cout << "Lower bound of 2.0: " << *res << "\n";
        }
    }