简体   繁体   中英

Forward iterator with a moving end()

So, I'm designing a class which connects (over network) to a service to receive some data. I don't know how man data points I will be receiving in advance. Nevertheless I was wondering, if there is a way to make this class iterable using a forward_iterator in order to enjoy the STL in its full glory. My idea was something like:

self_type operator++() {
  // if there are some locally cached data points left return next
  // else connect to service again to receive the next batch of data
}

However, as I cannot provide a valid end() , I'm curious, if this is somehow still possible to do.

An alternative (and iterator-less) interface would probably look something like:

bool hasMoreDataPoints() const;
DataPoint& getNext();

which obviously won't work with any STL-algorithm.

Do as the standard library do with istream_iterator : when you run out of data, set your iterator state such that it compares equal to a default-constructed object of that type. And then there's your end() equivalent.

I suppose there is some type of storage which you use in your class for caching, eg a std::vector . You can then just expose its std::begin() and std::end() iterators (in all the usual forms). Algorithms then directly work on the underlying container, and use the container-iterator's member functions like operator++ , operator== and so on.

In case you need to introduce more logic, you need to create your custom iterator. Such can be basically done by composition, ie write a new class which contains an iterator corresponding to your storage container, and expose all functionality you need while adjusting it accordingly.


EDIT: as you said you use a list:

struct DataPoints
{
    std::list<double> _list; 
    auto begin() const
    {
        return _list.begin();
    }
    auto end() const
    {
        return _list.end();
    }
    //other versions: non-const begin and end, cbegin, cend
}

That's it already for the simple approach. You can use that just as a normal list:

DataPoints d;
std::find(d.begin(), d.end(), 10.0);

As said, if you need more logic, you probably need to write a custom iterator.

However, as I cannot provide a valid end(), I'm curious, if this is somehow still possible ....

You could use any of the container classes that comes with STL. Assume you are using a vector or a list or any other suitable container. Just use what's provided by STL and write your own wrapper

vector<datapoint> mydpvector;

//as data comes in
mydpvector.push_back(newdp);

vector<datapoint>::const_iterator cit=mydpvector.begin();
//now iterate everytime over the container

for(cit;cit!=mydpvector.end();cit++)
{
//get the data you need
}

//alternately if you need just the last element do this
mostrecentdp = mydpvector.back();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM