Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sequence iterator? Isn't there one in boost?

From time to time I am feeling the need for a certain kind of iterator (for which I can't make up a good name except the one prefixed to the title of this question).

Suppose we have a function (or function object) that maps an integer to type T. That is, we have a definition of a mathematical sequence, but we don't actually have it stored in memory. I want to make an iterator out of it. The iterator class would look something like this:

template <class F, class T>
class sequence_iterator : public std::iterator<...>
{
    int i;
    F f;
    public:
    sequence_iterator (F f, int i = 0):f(f), i(i){}
    //operators ==, ++, +, -, etc. will compare, increment, etc. the value of i.
    T operator*() const
    {
        return f(i);
    }    
};

template <class T, class F>
sequence_iterator<F, T> make_sequence_iterator(F f, int i)
{
    return sequence_iterator<F, T>(f, i);
}

Maybe I am being naive, but I personally feel that this iterator would be very useful. For example, suppose I have a function that checks whether a number is prime or not. And I want to count the number of primes in the interval [a,b]. I'd do this;

int identity(int i)
{
   return i;
}
count_if(make_sequence_iterator<int>(identity, a), make_sequence_iterator<int>(identity, b), isPrime);

Since I have discovered something that would be useful (at least IMHO) I am definitely positive that it exists in boost or the standard library. I just can't find it. So, is there anything like this in boost?. In the very unlikely event that there actually isn't, then I am going to write one - and in this case I'd like to know your opinion whether or not should I make the iterator_category random_access_iterator_tag. My concern is that this isn't a real RAI, because operator* doesn't return a reference.

Thanks in advance for any help.

like image 658
Armen Tsirunyan Avatar asked Aug 07 '11 08:08

Armen Tsirunyan


1 Answers

boost::counting_iterator and boost::transform_iterator should do the trick:

template <typename I, typename F>
boost::transform_iterator<
    F,
    boost::counting_iterator<I>>
make_sequence_iterator(I i, F f)
{
    return boost::make_transform_iterator(
        boost::counting_iterator<I>(i), f);
}

Usage:

std::copy(make_sequence_iterator(0, f), make_sequence_iterator(n, f), out);
like image 158
Alexandre C. Avatar answered Sep 24 '22 16:09

Alexandre C.