returning an iterator 'concept'

T

Taras_96

Hi everyone,

I have a class which is essentially a fancy wrapper for a stack. One
of the functions returns an iterator to the underlying data structure
(the stack), so that clients can iterate over the contents. However,
in line with OO principles, I don't want to return an stack iterator,
as this would expose the implementation of the class - if I decide to
change the data structure to a vector, then client code may be broken.
Clients shouldn't need to care what type of iterator they are using,
they just need to be able to iterate.

One post suggested that you typedef the iterator in the class
definition, and clients would refer to the typedef'ed name instead of
the actual name. This would fix the above problem in that client code
that has hardcoded the iterator type will not be broken:

stack<int>::iterator it = foo.getIterator(); // this will break if
class Foo's underlying data structure becomes a vector, however

putting a typedef inside the class:

typdef stack<int>::iterator FooIterator;

then using this typedef

FooIterator it = foo.getIterator(); // this will not break if the
underlying data structure changes to a vector, as long as we change
the typedef

However, this is still not quite what I need. Suppose I originally
return an *actual* iterator type of vector<int>::iterator, and then
change this to return an *actual* iterator type of
list<int>::iterator.

Any client code that used the += operator on the FooIterator would now
be broken, as the list iterator does not implement this operator.

What essentially I would like to do is to return an iterator type
interface which the client must conform to. I would like to return an
interface similar to the ForwardIterator concept. However, you can not
return a 'concept'. Is there an ADT that already exists in C++ which
specifies an interface to a ForwardIterator concept? I could create an
ADT myself but I would think that this would already exist in C++.

On a side note, is it generally a bad idea to return a typedef'ed
iterator? As in the example I gave above, because you are not
restricting what the client can use (you're not telling the client
what he can/can not use), when you change the class behind the
typdedef client code may break. Of course you could tell the client
via documentation what he can use, but if you're going to do this you
might as well return an interface (ie: ADT).
 
V

Victor Bazarov

Taras_96 said:
[..] Suppose I originally
return an *actual* iterator type of vector<int>::iterator, and then
change this to return an *actual* iterator type of
list<int>::iterator.

Don't. Implement your own iterator class and give it persistent
properties. Make sure that it can be constructed from the iterator
to the container your stack uses, if you're going to pass those to
your iterator's constructor.
[..]

On a side note, is it generally a bad idea to return a typedef'ed
iterator?

There is no "generally" here. In your case you obviously don't
want to do that. Somebody else might.

V
 
T

Taras_96

Taras_96 wrote:

There is no "generally" here. In your case you obviously don't
want to do that. Somebody else might.

Let me rephrase then :). In what cases, if any, would you want to
return a typedef'd iterator and by doing so not break any good
programming practices/concepts/styles (as defined by yourself)?
 
V

Victor Bazarov

Taras_96 said:
Let me rephrase then :). In what cases, if any, would you want to
return a typedef'd iterator and by doing so not break any good
programming practices/concepts/styles (as defined by yourself)?

You can return a typedef'ed iterator if you know that by design your
class is never going to change the fact that its iterator is the
a std::blah<>::iterator (which means that the container it's going
to iterate is of type std::blah<>). As soon as you say that "I may
want to substitute 'std::blah' with 'std::blahblah' or 'myown::blah'
later", then you can't return a typedef'ed iterator. Your iterator
should probably privately derive from the standard one, and then
you also need to provide iterator_traits (for those who might find
it useful to refer to a specialisation of your iterator, or just to
make your iterator usable with standard algorithms).

V
 
B

bjeremy

Hi everyone,

I have a class which is essentially a fancy wrapper for a stack. One
of the functions returns an iterator to the underlying data structure
(the stack), so that clients can iterate over the contents. However,
in line with OO principles, I don't want to return an stack iterator,
as this would expose the implementation of the class - if I decide to
change the data structure to a vector, then client code may be broken.
Clients shouldn't need to care what type of iterator they are using,
they just need to be able to iterate.

One post suggested that you typedef the iterator in the class
definition, and clients would refer to the typedef'ed name instead of
the actual name. This would fix the above problem in that client code
that has hardcoded the iterator type will not be broken:

stack<int>::iterator it = foo.getIterator(); // this will break if
class Foo's underlying data structure becomes a vector, however

putting a typedef inside the class:

typdef stack<int>::iterator FooIterator;

then using this typedef

FooIterator it = foo.getIterator(); // this will not break if the
underlying data structure changes to a vector, as long as we change
the typedef

However, this is still not quite what I need. Suppose I originally
return an *actual* iterator type of vector<int>::iterator, and then
change this to return an *actual* iterator type of
list<int>::iterator.

Any client code that used the += operator on the FooIterator would now
be broken, as the list iterator does not implement this operator.

What essentially I would like to do is to return an iterator type
interface which the client must conform to. I would like to return an
interface similar to the ForwardIterator concept. However, you can not
return a 'concept'. Is there an ADT that already exists in C++ which
specifies an interface to a ForwardIterator concept? I could create an
ADT myself but I would think that this would already exist in C++.

On a side note, is it generally a bad idea to return a typedef'ed
iterator? As in the example I gave above, because you are not
restricting what the client can use (you're not telling the client
what he can/can not use), when you change the class behind the
typdedef client code may break. Of course you could tell the client
via documentation what he can use, but if you're going to do this you
might as well return an interface (ie: ADT).

A suggestion is to roll-you-own iterator. You use an Adapter and wrap
the iterator. Declare and Iterator Abstract Base Class that you can
expose publicly and then create concrete itertators for whatever
containers you want to use. To your clients, all they need to know
about is the ABC interface
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,989
Messages
2,570,207
Members
46,783
Latest member
RickeyDort

Latest Threads

Top