By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,652 Members | 1,694 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,652 IT Pros & Developers. It's quick & easy.

Is there such an iterator?

P: n/a
I've got a bunch of file_iterator<> (http://tinyurl.com/3uuxa)
begin/end pairs that point to various chunks in a file. It would be
super-cool, in my program, to be able to treat all of these ranges as
though they were one huge range. I'm envisioning something along the
lines of a library facility that provides an iterator type that
encapsulates a set of ranges and abstracts out code to handle
traversal through all of them as though all the little sets of ranges
were one big one.

Maybe this will help clarify:

int main(void)
{
vector<pair<file_iterator<>, file_iterator<> >
ranges(2);

ranges.at(0).first = file_iterator<>("somefile.txt");
ranges.at(0).second = ranges.at(0).first + 5;

ranges.at(1).first = ranges.at(0).second + 5;
ranges.at(1).second = ranges.at(1).first + 5;

// this is fictional
typedef single_range_emulating_iterator</*some stuff here*/>
sre_iterator;

sre_iterator begin(ranges);
sre_iterator end = begin.make_end(); // or something

// this results in a traversal through all the ranges.
for_each(begin, end, some_operation());
}

Is there such a thing? Is such a thing possible?

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a
"Arturo Cuebas" <do**@want.spam> wrote in message
I've got a bunch of file_iterator<> (http://tinyurl.com/3uuxa)
begin/end pairs that point to various chunks in a file. It would be
super-cool, in my program, to be able to treat all of these ranges as
though they were one huge range. I'm envisioning something along the
lines of a library facility that provides an iterator type that
encapsulates a set of ranges and abstracts out code to handle
traversal through all of them as though all the little sets of ranges
were one big one.


There is no such segmented iterator in the standard library, though the
implementation of std::deque is a little along the lines you describe.
Wonder if boost has such a class. Anyway, it would be something like

template <class Iter>
class segmented_iterator {
public:
typedef typename std::iterator_traits<Iter>::value_type value_type;
typedef typename std::iterator_traits<Iter>::pointer pointer;
segmented_iterator(const std::vector<Iter>& begins, const
std::vector<Iter>& ends);
reference operator*() const { return *d_iter; }
pointer operator->() const;
const segmented_iterator operator++(int) {
segmented_iterator out = *this;
++*this;
return out;
}
segmented_iterator operator++() {
++d_iter;
if (d_iter == d_ends[d_current]) {
++d_current;
if (d_current < d_begins.size()) {
d_iter = d_begins[d_current];
}
return *this;
}
}
bool operator!=(const segmented_iterator& that) const {
return
this->d_current != that.d_current
|| this->d_iter != that.d_iter
;
}
private:
std::vector<Iter> d_begins;
std::vector<Iter> d_ends;
size_type d_current;
Iter d_iter;
};

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #2

P: n/a
Arturo Cuebas wrote:
I've got a bunch of file_iterator<> (http://tinyurl.com/3uuxa)
begin/end pairs that point to various chunks in a file. It would be
super-cool, in my program, to be able to treat all of these ranges as
though they were one huge range. I'm envisioning something along the
lines of a library facility that provides an iterator type that
encapsulates a set of ranges and abstracts out code to handle
traversal through all of them as though all the little sets of ranges
were one big one.


I don't know whether there is a ready made iterator for this (you
might want to check <http://www.boost.org/>) but it seems fairly
easy to create it: You just store your vector of pairs of iterators
(or a pointer to the corresponding vector) in one of the iterators.
The past-the-end iterator would store no data.

Effectively, you would create an iterator iterating over a sequence
of segments (quite similar to the iterator of 'std::deque'): It
would store information about the current segment and the position
of the segment in the vector of pairs. Advancing the iterator would
actually advance an iterator into the current segment switching to
the next segment if it hits the end of the current segment. If all
segments are processed, the iterator would compare equal to the
past the end iterator.

Here is an untested sketch of the code:

| template <typename Cont>
| class segment_pair_iterator
| {
| public:
| typedef typename Cont::value_type::first_type seg_iterator;
| segment_pair_iterator(): m_cont() { init(); }
| explicit
| segment_pair_iterator(Cont const& cont): m_cont(cont) { init(); }
|
| typename std::iterator_traits<seg_iterator>::reference
| operator*() const { return *m_seg_current; }
| segment_pair_iterator& operator++() {
| if (++m_seg_current == m_seg_end) {
| if (++m_cur_segment != m_cont.end()) {
| m_seg_current = m_cur_segment->first;
| m_seg_end = m_cur_segment->second;
| }
| }
| return *this;
| }
|
| bool operator== (segment_pair_iterator const& it) const {
| return (m_cur_segment == m_cont.end())
| == (it->m_cur_segment == it->m_cont.end());
| }
| // more members, mostly with derived logic...
| private:
| void init() {
| m_cur_segment = m_cont.begin();
| if (m_cur_segment != m_cont.end()) {
| m_seg_current = m_cur_segment->first;
| m_seg_end = m_cur_segment->second;
| }
| }
| Cont m_cont;
| typename Cont::const_iterator m_cur_segment;
| seg_iterator m_seg_current;
| seg_iterator m_seg_end;
| };
--
<mailto:di***********@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.contendix.com> - Software Development & Consulting
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #3

P: n/a
Such a class wouldn't be that difficult to write, here's something that
I cobbled together just now (standard warning applies; hasn't been
tested, yadda, yadda, yadda), should give you an idea where to start
----Begin code ---
#include <deque>
#include <utility>

template<typename Iterator>
class DisjointIterator
{
public:
typedef std::input_iterator_tag iterator_category;
typedef typename std::iterator_traits<Iterator>::value_type
value_type;
typedef typename std::iterator_traits<Iterator>::difference_type
difference_type;
typedef typename std::iterator_traits<Iterator>::pointer pointer;
typedef typename std::iterator_traits<Iterator>::reference reference;
typedef const reference const_reference;
typedef const pointer const_pointer;

private:
bool m_is_end;
std::deque<std::pair<Iterator,Iterator> > m_iters; //Pairs of begin
and end iterators
Iterator m_iter;
Iterator m_next_end;

void pop_next_iterator_range()
{
m_is_end = m_iters.empty();
if(!m_is_end)
{
m_iter = m_iters.front().first;
m_next_end = m_iters.front().second;
m_iters.pop_front();
}
}

public:
DisjointIterator() : m_is_end(true) {}
DisjointIterator(const DisjointIterator &other) :
m_is_end(other.m_is_end), m_iters(other.m_iters), m_iter(other.m_iter),
m_next_end(other.m_next_end) {}
template<typename IteratorListInputIterator> //Should be an
InputIterator into a sequence of std::pair<Iterator,Iterator>
DisjointIterator(IteratorListInputIterator iter,
IteratorListInputIterator end)
{
for(;iter != end; ++iter)
{
if(iter->first != iter->second)
{
m_iters.push_back(*iter);
}
}

pop_next_iterator_range();
}

DisjointIterator &operator=(const DisjointIterator &other)
{
m_is_end = other.m_is_end;
m_iters = other.m_iters;
m_iter = other.m_iter;
m_next_end = other.m_next_end;
return *this;
}

DisjointIterator &operator++()
{
if(!m_is_end)
{
++m_iter;
if(m_iter == m_next_end)
{
pop_next_iterator_range();
}
}
return *this;
}

DisjointIterator operator++(int)
{
DisjointIterator temp(*this);
++*this;
return temp;
}

bool operator==(const DisjointIterator &other) const
{
if(m_is_end)
{
return other.m_is_end;
}
else
{
return m_iter == other.m_iter;
}
}

bool operator!=(const DisjointIterator &other) const { return
!operator==(other); }
reference operator*() { return *m_iter; }
const_reference operator*() const { return *m_iter; }

pointer operator->() { return &(operator*()); }
const_pointer operator->() const { return &(operator*()); }
};
---- end code ----

And, for a sanity check, I just used it like so:

---- begin code ----
#include <vector>
using std::vector;

#include <utility>
using std::pair;
using std::make_pair;

#include <iterator>
using std::ostream_iterator;

#include <iostream>
using std::cout;

int main()
{
vector<int> vec;

for(int i = 0; i<100; ++i)
{
vec.push_back(i);
}

vector<pair<vector<int>::iterator, vector<int>::iterator> > iters;

iters.push_back(make_pair(vec.begin(), vec.begin()+3));
iters.push_back(make_pair(vec.begin()+20, vec.begin()+20));
iters.push_back(make_pair(vec.begin()+21, vec.begin()+30));
iters.push_back(make_pair(vec.begin()+90, vec.end()));
iters.push_back(make_pair(vec.begin()+20, vec.begin()+25));

DisjointIterator<vector<int>::iterator>
disjoint_begin(iters.begin(), iters.end());
DisjointIterator<vector<int>::iterator> disjoint_end;

std::copy(disjoint_begin, disjoint_end, ostream_iterator<int>(cout,
", "));

cout << "\n";

return 0;
}
---- end code ----

Which produced the following output:
0, 1, 2, 21, 22, 23, 24, 25, 26, 27, 28, 29, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99, 20, 21, 22, 23, 24,
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #4

P: n/a
On 01/11/2005 03:48 AM, Dietmar Kuehl wrote:
Arturo Cuebas wrote:
I've got a bunch of file_iterator<> (http://tinyurl.com/3uuxa)
begin/end pairs that point to various chunks in a file. It would be
super-cool, in my program, to be able to treat all of these ranges as
though they were one huge range. I'm envisioning something along the
[snip] I don't know whether there is a ready made iterator for this (you
might want to check <http://www.boost.org/>) but it seems fairly

There's also something in the boost files that does something
similar. The file is:

http://groups.yahoo.com/group/boost/...tor%20Adaptor/

You have to join the group to see the file, but that's not hard.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.