473,387 Members | 1,517 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Virtual Iterators

I have a problem with an abstract interface class whose implementation
classes need to return different iterator types (but with the same
value_types etc).

Classes A and B both conform to the same abstract Interface class. Interface
has a pair of virtual functions begin() and end() that generate a typical
STL style range. Classes A and B provide different implementations, maybe
using different types of container. The problem is that, to conform to the
interface, A and B must return the same type (or a derived type). They can
not do this directly as their containers (and hence their iterators) are of
different types.

class Interface
{
public:
virtual VirtualIterator begin() = 0;
virtual VirtualIterator end() = 0;
};

class A : public Interface
{
public:
virtual VirtualIterator begin() {return
make_virtual_iterator(container_.begin());}
virtual VirtualIterator end() {return
make_virtual_iterator(container_.end());}
private:
OneKindOfContainer container_;
};

class B : public Interface
{
public:
virtual VirtualIterator begin() {return
make_virtual_iterator(container_.begin());}
virtual VirtualIterator end() {return
make_virtual_iterator(container_.end())}
private:
AnotherKindOfContainer container_;
};

I think I see how to solve this problem by creating (as the example hints
at) a kind of VirtualIterator class that maintains a pointer to heap based
copy of the real iterator. But this issue must be fairly common and I would
much rather reuse a tried and tested solution than roll my own. I looked at
the boost iterator library but it does not seem to provide what I am looking
for. This made me a bit concerned because it seems to be very well thought
out and comprehensive. Is there something fundamentally wrong with what I am
considering here? Or perhaps there is a really trivial solution I am
overlooking?

Richard Forrest


Jul 22 '05 #1
9 4988
"richard.forrest1" <ri**************@ntlworld.com> wrote...
I have a problem with an abstract interface class whose implementation
classes need to return different iterator types (but with the same
value_types etc).

Classes A and B both conform to the same abstract Interface class. Interface has a pair of virtual functions begin() and end() that generate a typical
STL style range. Classes A and B provide different implementations, maybe
using different types of container. The problem is that, to conform to the
interface, A and B must return the same type (or a derived type). They can
not do this directly as their containers (and hence their iterators) are of different types.

class Interface
{
public:
virtual VirtualIterator begin() = 0;
virtual VirtualIterator end() = 0;
};

class A : public Interface
{
public:
virtual VirtualIterator begin() {return
make_virtual_iterator(container_.begin());}
virtual VirtualIterator end() {return
make_virtual_iterator(container_.end());}
private:
OneKindOfContainer container_;
};

class B : public Interface
{
public:
virtual VirtualIterator begin() {return
make_virtual_iterator(container_.begin());}
virtual VirtualIterator end() {return
make_virtual_iterator(container_.end())}
private:
AnotherKindOfContainer container_;
};

I think I see how to solve this problem by creating (as the example hints
at) a kind of VirtualIterator class that maintains a pointer to heap based
copy of the real iterator. But this issue must be fairly common and I would much rather reuse a tried and tested solution than roll my own. I looked at the boost iterator library but it does not seem to provide what I am looking for. This made me a bit concerned because it seems to be very well thought
out and comprehensive. Is there something fundamentally wrong with what I am considering here? Or perhaps there is a really trivial solution I am
overlooking?


For now, having only thought about your problem for a minute, I have only
one question: what are you going to do with 'VirtualIterator'? What does
its interface look like? I can see it that you are going to compare its
value to 'end' to know when to stop iterating, but I cannot imagine yet
if you have two different and unrelated containers, what else you could
do with a VirtualIterator object. Unless, of course, it's an iterator that
conforms to the iterator semantics laid out in the Standard, then it has to
have 'value_type' and 'reference' and ...

Do you have the answers?

V
Jul 22 '05 #2
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:s_pbc.169165$po.978501@attbi_s52...
"richard.forrest1" <ri**************@ntlworld.com> wrote...
I have a problem with an abstract interface class whose implementation
classes need to return different iterator types (but with the same
value_types etc).

Classes A and B both conform to the same abstract Interface class.

Interface
has a pair of virtual functions begin() and end() that generate a typical STL style range. Classes A and B provide different implementations, maybe using different types of container. The problem is that, to conform to the interface, A and B must return the same type (or a derived type). They can not do this directly as their containers (and hence their iterators) are

of
different types.

class Interface
{
public:
virtual VirtualIterator begin() = 0;
virtual VirtualIterator end() = 0;
};

class A : public Interface

For now, having only thought about your problem for a minute, I have only
one question: what are you going to do with 'VirtualIterator'? What does
its interface look like? I can see it that you are going to compare its
value to 'end' to know when to stop iterating, but I cannot imagine yet
if you have two different and unrelated containers, what else you could
do with a VirtualIterator object. Unless, of course, it's an iterator that conforms to the iterator semantics laid out in the Standard, then it has to have 'value_type' and 'reference' and ...


I imagine you can pass VirtualIterator to standard functions like std::copy.
Here is one implementation. It has to be copy constructible, so it won't be
a polymorphic class. It will define a nested polymorphic abstract class
implement that represents the real iterator (though it does not have to be a
nested class), and this class will have pure virtual functions for cloning,
assigment, increment, decrement, equal. VirtualIterator will contain a
std::auto_ptr<implement> or the like. Derived classes like class A above
will define concrete iterator implement classes. Here is my implementation.
template <class T>
class poly_iterator
{
public:
typedef std::forward_iterator_tag iterator_category;
typedef T value_type ;
typedef T & reference ;
...

class implement; // abstract class

poly_iterator(implement * iter) : d_iter(iter) {} // take ownership of
object
poly_iterator(const poly_iterator& that) :
d_iter(that.d_iter->clone()) { }
poly_iterator& operator=(const poly_iterator& that);
~poly_iterator() { delete d_iter; }

bool operator==(const poly_iterator& that) const
{ same(*this,that); return this->d_iter->equal(*that.d_iter); }
bool operator!=(const poly_iterator& that) const;

reference operator*() const { return d_iter->get(); }
pointer operator->() const { return &d_iter->get(); }
poly_iterator& operator++() { d_iter->next(); return *this; }
public:
class implement
{
public:
virtual ~implement() { }
virtual implement * clone() const = 0;
virtual bool equal(const implement&) const = 0;
virtual T& get() const = 0;
virtual void next() = 0;
virtual void prev() = 0;
};

template <class Iter>
class usualimplement : public implement {
public:
typedef Iter actual_iterator;
explicit usualimplement(Iter iter) : d_iter(iter) { }
usualimplement * clone() const { return new
usualimplement(*this); }
bool equal(const implement& that) const { return this->d_iter
==static_cast<const usualimplement&>(that).d_iter; }
T& get() const { return *d_iter; }
void next() { ++d_iter; }
void prev() { --d_iter; }
private:
Iter d_iter;
};
private:
implement * d_iter; // dynamically created object

static void same(const poly_iterator& lhs, const poly_iterator& rhs)
{ assert(typeid(*lhs.d_iter)==typeid(*rhs.d_iter)); }
};
Jul 22 '05 #3
"Siemel Naran" <Si*********@REMOVE.att.net> wrote...
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:s_pbc.169165$po.978501@attbi_s52...
"richard.forrest1" <ri**************@ntlworld.com> wrote...
I have a problem with an abstract interface class whose implementation
classes need to return different iterator types (but with the same
value_types etc).

Classes A and B both conform to the same abstract Interface class.

Interface
has a pair of virtual functions begin() and end() that generate a typical STL style range. Classes A and B provide different implementations, maybe using different types of container. The problem is that, to conform to the interface, A and B must return the same type (or a derived type). They can not do this directly as their containers (and hence their iterators)
are of
different types.

class Interface
{
public:
virtual VirtualIterator begin() = 0;
virtual VirtualIterator end() = 0;
};

class A : public Interface
For now, having only thought about your problem for a minute, I have

only one question: what are you going to do with 'VirtualIterator'? What does its interface look like? I can see it that you are going to compare its
value to 'end' to know when to stop iterating, but I cannot imagine yet
if you have two different and unrelated containers, what else you could
do with a VirtualIterator object. Unless, of course, it's an iterator

that
conforms to the iterator semantics laid out in the Standard, then it has

to
have 'value_type' and 'reference' and ...


I imagine you can pass VirtualIterator to standard functions like

std::copy.

std::copy is not a function. It's a template.
Here is [...]


I still would like to hear from the OP...
Jul 22 '05 #4

"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:JFqbc.164692$_w.1794464@attbi_s53...
"Siemel Naran" <Si*********@REMOVE.att.net> wrote...
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:s_pbc.169165$po.978501@attbi_s52...
"richard.forrest1" <ri**************@ntlworld.com> wrote...

I have just done a Google search on "polymorphic iterator" and it is a well
known concept. There is even a reference to it in GOF (page 271).

It seems I was just calling it the wrong thing.

Thanks for you help guys,

Richard
Jul 22 '05 #5

----- Original Message -----
From: "Victor Bazarov" <v.********@comAcast.net>
Newsgroups: comp.lang.c++
Sent: Saturday, April 03, 2004 5:00 AM
Subject: Re: Virtual Iterators

"Siemel Naran" <Si*********@REMOVE.att.net> wrote...
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:s_pbc.169165$po.978501@attbi_s52...
"richard.forrest1" <ri**************@ntlworld.com> wrote...

> I have a problem with an abstract interface class whose implementation > classes need to return different iterator types (but with the same
> value_types etc).
>
For now, having only thought about your problem for a minute, I have only one question: what are you going to do with 'VirtualIterator'? What does its interface look like? I can see it that you are going to compare its value to 'end' to know when to stop iterating, but I cannot imagine yet if you have two different and unrelated containers, what else you could do with a VirtualIterator object. Unless, of course, it's an iterator

that
conforms to the iterator semantics laid out in the Standard, then it
has to
have 'value_type' and 'reference' and ...


First of all I take Siemel Narans hint that VirtualIterator would be better
named PolymorphicIterator and have done so from now on. This is really a
response to Victor's questions. I am looking at Siemel's example code snipet
now (thanks) and will respond to this when I think I understand it properly.

The PolymorphicIterator conforms to one of the STL iterator concepts.
The purpose of PolymorphicIterator is that any client of an Interface object
can iterate through all or part of the range [begin(),end()) without having
to know the type of the underlying container. Of course the iterators
underlying the PolymorphicIterator must have the same value_type etc. They
must also conform to the PolymorphicIterator's STL iterator concept.

I am not trying to write a "universal container class" or anything silly
like that. All I want to do is provide a limited interface for a client to
be able to read the a range of attribute values.

Let me give a simple (contrived) example of the use of this. We have an
interface class AbstractPolygon and two derived classes ConstantPolygon and
ChangablePolygon. A ConstantPolygon object represents a polygon that can not
be edited. A ChangablePolygon object represents a polygon whose vertices may
be inserted or erased.

AbstractPolygon provides a pair of virtual abstract functions vertexBegin(),
vertexEnd() that provide a sequence of the vertices of the polygon.
ConstantPolygon and ChangablePolygon provide implementations of these
functions. ConstantPolygon's underlying representation happens to be a
vector of vertices. But ChangablePolygon's underlying representation is
chosen to be a linked list of vertices.

Now clients that perform constant operations (e.g. rendering, calculating
area etc) just need to use AbstractPolygons. They use the AbstractPolygon's
vertexBegin() and vertexEnd() functions to obtain the start and end of the
range of vertices and iterate through it, doing whatever they do. The
PolymorphicIterator hides the fact that the underlying iterator may be a
vector<Vertex>::const_iterator or a list<Vertex>::const_iterator.

Of course there are other ways to solve this problem. We could provide a new
virtual abstract member function in AbstractPolygon and a corresponding
implementation in each derived class for every possible use of the
iterators. But this couples the algorithms too tightly to the polygons.
Adding new algorithms would be very inconvienient. Using the Visitor pattern
might help in some ways but adds its own restrictions. In this case
PolymorphicIterators are what are required.
Thanks for your comments.

Richard


Jul 22 '05 #6

In case anyone is interested I have just discovered that Boost has a
polymorphic iterator class being developped right now.
They call it boost::any_iterator. It sounds like just what I want :-))))

See link for details.
http://www.crystalclearsoftware.com/...?LibrariesUnde
rConstruction
Thanks once again.

Richard
Jul 22 '05 #7

"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:JFqbc.164692$_w.1794464@attbi_s53...
"Siemel Naran" <Si*********@REMOVE.att.net> wrote...
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:s_pbc.169165$po.978501@attbi_s52...
"richard.forrest1" <ri**************@ntlworld.com> wrote...

I have just done a Google search on "polymorphic iterator" and it is a well
known concept. There is even a reference to it in GOF (page 271).

It seems I was just calling it the wrong thing.

Thanks for you help guys,

Richard
Jul 22 '05 #8

----- Original Message -----
From: "Victor Bazarov" <v.********@comAcast.net>
Newsgroups: comp.lang.c++
Sent: Saturday, April 03, 2004 5:00 AM
Subject: Re: Virtual Iterators

"Siemel Naran" <Si*********@REMOVE.att.net> wrote...
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:s_pbc.169165$po.978501@attbi_s52...
"richard.forrest1" <ri**************@ntlworld.com> wrote...

> I have a problem with an abstract interface class whose implementation > classes need to return different iterator types (but with the same
> value_types etc).
>
For now, having only thought about your problem for a minute, I have only one question: what are you going to do with 'VirtualIterator'? What does its interface look like? I can see it that you are going to compare its value to 'end' to know when to stop iterating, but I cannot imagine yet if you have two different and unrelated containers, what else you could do with a VirtualIterator object. Unless, of course, it's an iterator

that
conforms to the iterator semantics laid out in the Standard, then it
has to
have 'value_type' and 'reference' and ...


First of all I take Siemel Narans hint that VirtualIterator would be better
named PolymorphicIterator and have done so from now on. This is really a
response to Victor's questions. I am looking at Siemel's example code snipet
now (thanks) and will respond to this when I think I understand it properly.

The PolymorphicIterator conforms to one of the STL iterator concepts.
The purpose of PolymorphicIterator is that any client of an Interface object
can iterate through all or part of the range [begin(),end()) without having
to know the type of the underlying container. Of course the iterators
underlying the PolymorphicIterator must have the same value_type etc. They
must also conform to the PolymorphicIterator's STL iterator concept.

I am not trying to write a "universal container class" or anything silly
like that. All I want to do is provide a limited interface for a client to
be able to read the a range of attribute values.

Let me give a simple (contrived) example of the use of this. We have an
interface class AbstractPolygon and two derived classes ConstantPolygon and
ChangablePolygon. A ConstantPolygon object represents a polygon that can not
be edited. A ChangablePolygon object represents a polygon whose vertices may
be inserted or erased.

AbstractPolygon provides a pair of virtual abstract functions vertexBegin(),
vertexEnd() that provide a sequence of the vertices of the polygon.
ConstantPolygon and ChangablePolygon provide implementations of these
functions. ConstantPolygon's underlying representation happens to be a
vector of vertices. But ChangablePolygon's underlying representation is
chosen to be a linked list of vertices.

Now clients that perform constant operations (e.g. rendering, calculating
area etc) just need to use AbstractPolygons. They use the AbstractPolygon's
vertexBegin() and vertexEnd() functions to obtain the start and end of the
range of vertices and iterate through it, doing whatever they do. The
PolymorphicIterator hides the fact that the underlying iterator may be a
vector<Vertex>::const_iterator or a list<Vertex>::const_iterator.

Of course there are other ways to solve this problem. We could provide a new
virtual abstract member function in AbstractPolygon and a corresponding
implementation in each derived class for every possible use of the
iterators. But this couples the algorithms too tightly to the polygons.
Adding new algorithms would be very inconvienient. Using the Visitor pattern
might help in some ways but adds its own restrictions. In this case
PolymorphicIterators are what are required.
Thanks for your comments.

Richard


Jul 22 '05 #9

In case anyone is interested I have just discovered that Boost has a
polymorphic iterator class being developped right now.
They call it boost::any_iterator. It sounds like just what I want :-))))

See link for details.
http://www.crystalclearsoftware.com/...?LibrariesUnde
rConstruction
Thanks once again.

Richard
Jul 22 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: richard.forrest1 | last post by:
I have a problem with an abstract interface class whose implementation classes need to return different iterator types (but with the same value_types etc). Classes A and B both conform to the...
3
by: Mark Turney | last post by:
Problem: I have a vector full of two different derived class objects (class B and class C) that are derived from the same base class A. I want to loop through vector and invoke a member function...
18
by: deancoo | last post by:
I have gotten into the habit of often using copy along with an insert iterator. There are scenarios where I process quite a lot of data this way. Can someone give me a general feel as to how much...
24
by: Lasse Vågsæther Karlsen | last post by:
I need to merge several sources of values into one stream of values. All of the sources are sorted already and I need to retrieve the values from them all in sorted order. In other words: s1 = ...
8
by: Asfand Yar Qazi | last post by:
Hi, I have the following header file in my 'everything useful I think of in one place' library: ============= BEGIN CODE SNIPPET =========== /** All classes that derive from this obtain a...
2
by: Amadeus W. M. | last post by:
Template member functions cannot be virtual - I know - but is there any way to simulate that (other than making the entire class templated, with non-templated members). What I have is this: ...
2
by: ma740988 | last post by:
typedef std::vector < std::complex < double > > complex_vec_type; // option1 int main() { complex_vec_type cc ( 24000 ); complex_vec_type dd ( &cc, &cc ); } versus
5
by: toton | last post by:
Hi, I want a few of my class to overload from a base class, where the base class contains common functionality. This is to avoid repetition of code, and may be reducing amount of code in binary,...
18
by: desktop | last post by:
1) I have this code: std::list<intmylist; mylist.push_back(1); mylist.push_back(2); mylist.push_back(3); mylist.push_back(4);
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.