iterator classes

T

Taras_96

Hi everyone,

I read on a post that:

"You have a problem because vector<T>::iterator supports += (for
instance) and list<T>::iterator does not. Either you'll have to dumb
down your vector iterator by removing operator += or you'll have to
generate a run time error when anyone tries to use += on your list
iterator. Neither seems very acceptable, you are substituting run
time
checks for compile time type safety. "

Where is this interface explicitly specified? Is it on the sgi
website?

Thanks
 
V

Victor Bazarov

Taras_96 said:
I read on a post that:

"You have a problem because vector<T>::iterator supports += (for
instance) and list<T>::iterator does not. Either you'll have to dumb
down your vector iterator by removing operator += or you'll have to
generate a run time error when anyone tries to use += on your list
iterator. Neither seems very acceptable, you are substituting run
time
checks for compile time type safety. "

Where is this interface explicitly specified? Is it on the sgi
website?

The concepts of different iterators and operations they support are
defined by the language Standard document. Input iterator, output
iterator, bidirectional iterator, random access iterator. Read up
on those.

V
 
A

Andrey Tarasevich

Taras_96 said:
"You have a problem because vector<T>::iterator supports += (for
instance) and list<T>::iterator does not. Either you'll have to dumb
down your vector iterator by removing operator += or you'll have to
generate a run time error when anyone tries to use += on your list
iterator. Neither seems very acceptable, you are substituting run
time
checks for compile time type safety. "

I don't know the whole concept, but from the abstract point of view the
post you quoted is awfully misleading.

If you applied a '+=' operator to your iterator, it immediately means
that your algorithm relies on random access and therefore requires a
random access iterator.

If random access is indeed critical for your algorithm, it means that it
can't be applied to non-random-accessible data structures. In this case
it is perfectly fine that the algorithm will generate a compile-time
error when applied to, say, 'list<T>::iterator' (I don't know where that
poster got the idea that the error should happen at run-time. Maybe it
follows from the context that I don't see.).

The alternative approach would be to decide to "emulate" the
functionality of '+=' with a sequence of one-step advances (a sequence
of prefix '++'s for example). The key moment here is that the
"emulation" should only be performed for sequential iterators (like
'list<T>::iterator'), but not for true random-access iterators (like
'vector<T>::iterator'). The latter should continue to use '+='. This can
be easily achieved by using 'std::advance' instead of '+=' in your
algorithm. It will automatically "emulate" '+=' for sequential iterators
and use the native '+=' for random-access ones. That way you get the
best of both worlds: you preserve the performance of your algorithm with
'vector<T>::iterator', while still making it work with 'list<T>::iterator'.

It is up to you to choose which approach you want to use.
Where is this interface explicitly specified? Is it on the sgi
website?

C++ language specification includes the specification for the standard
library.
 
T

Taras_96

Thanks for the replies.

Both of you mentioned that the return types are specified in the STL
documentation. The STL documentation shows that for a vector that
begin() returns an 'iterator'.

http://www.sgi.com/tech/stl/Vector.html

iterator begin() Container Returns an iterator pointing to the
beginning of the vector.

From what I understand, this would be a typedef'd class inside the
vector definition.

"The answer is shamelessly dodgy: it depends. As far as the standard
containers go, the standard does not specify exactly what an iterator
is. What it does say is that, for example, the class vector has to at
least have a public typedef that looks like the following, where the
token unspecified is a type that can be whatever the implementation
wants:

// In <vector>, within the declaration of vector
typedef unspecified iterator;
typedef unspecified const_iterator;
" - http://www.oreillynet.com/pub/a/network/2005/10/18/what-is-iterator-in-c-plus-plus.html?page=3

So, from what the STL documentation is telling me, begin() will return
a class that satisfies the 'iterator' concept. However, the STL
documentation does not mention an iterator concept (it does mention
some other iterator concepts, such as trivial iterator, input
iterator, etc..)

So, how do I know the interface that the returned object from begin()
will have? Jossutti's 'C++ standard library' states that a vector
returns a random access iterator, but I haven't been able to find
reference to this in the documentation.

Victor, as a side note, doesn't leaving the implementation of
iterators up to a specific implementor create an opportunity to
produce unportable code? As mentioned in another thread that you have
contributed to, titled 'returning an iterator 'concept'', the actual
class behind the typedef'ed iterator could be anything that at the
least satisfies the iterator concept. If it in fact provides more than
that concept in implementation A, and a client uses that extra
functionality, then wouldn't the client code not necessarily be
portable to implementation B?
 
R

red floyd

Taras_96 said:
So, how do I know the interface that the returned object from begin()
will have? Jossutti's 'C++ standard library' states that a vector
returns a random access iterator, but I haven't been able to find
reference to this in the documentation.

1. Because the SGI documentation is not the Standard. I believe ISO/IEC
14882:2003 specifies that. My copy is at work, and I'm out of the
office for the time being, so somebody with a copy will have to check that.
Victor, as a side note, doesn't leaving the implementation of
iterators up to a specific implementor create an opportunity to
produce unportable code? As mentioned in another thread that you have
contributed to, titled 'returning an iterator 'concept'', the actual
class behind the typedef'ed iterator could be anything that at the
least satisfies the iterator concept. If it in fact provides more than
that concept in implementation A, and a client uses that extra
functionality, then wouldn't the client code not necessarily be
portable to implementation B?

To reprase your question: The C Standard doesn't specify how you should
implement printf(), only what it does. Since it's up to the library
implementor, doesn't that lead to a loss of portability?

So long as the iterators provided by your implementation's version of
the Standard Library match the interface defined by ISO/IEC 14882:2003,
and you code to the interface (as opposed to the implementation, i.e:
assuming vector iterators are pointers), you'll be fine.
 
J

James Kanze

Both of you mentioned that the return types are specified in
the STL documentation. The STL documentation shows that for a
vector that begin() returns an 'iterator'.

iterator begin() Container Returns an iterator pointing to the
beginning of the vector.
From what I understand, this would be a typedef'd class inside
the vector definition.

Might be. Could be anything, really, that results in a
vector<xxx>::iterator being a type which conforms to the concept
of a random access iterator. (In many early implementations of
the STL, it was a typedef to a pointer.)
The answer is shamelessly dodgy: it depends. As far as the
standard containers go, the standard does not specify exactly
what an iterator is.

Of course not. All it does is specify how to get one, how to
declare one, and what you can do with it. Anything more would
be over-specification.
What it does say is that, for example, the class vector has to
at least have a public typedef that looks like the following,
where the token unspecified is a type that can be whatever the
implementation wants:
// In <vector>, within the declaration of vector
typedef unspecified iterator;
typedef unspecified const_iterator;
" -http://www.oreillynet.com/pub/a/network/2005/10/18/what-is-iterator-i....

You've raised an interesting point. I don't think that the
intent is to require a typedef. Certainly in the requirements
section, all that is required is that container::iterator name a
type. Of hand, I would expect a nested class to be legal as
well.
So, from what the STL documentation is telling me, begin()
will return a class that satisfies the 'iterator' concept.
However, the STL documentation does not mention an iterator
concept (it does mention some other iterator concepts, such as
trivial iterator, input iterator, etc..)

The very first line about std::vector in the standard is "A
vector is a kind of sequence that supports random access
iterators." So the iterator type most meet the requirements of
a random access iterator. Requirements which are spelled out in
detail in §24.1.5 (called not surprisingly "Random access
iterators").
So, how do I know the interface that the returned object from
begin() will have? Jossutti's 'C++ standard library' states
that a vector returns a random access iterator, but I haven't
been able to find reference to this in the documentation.
Victor, as a side note, doesn't leaving the implementation of
iterators up to a specific implementor create an opportunity
to produce unportable code?

Of course. In practice, some implementations still use a
typedef to a pointer, others use a class, and there are things
that will work with one, and not with the other (due to the fact
that in one case, the ++ operator is a built-in operator, and in
the other, it is a member function). On the other hand, it
allows the implementation to be tuned to its user requirements.
(With a poor compiler, the pointer will probably be faster than
the class; the class will allow debugging implementations which
catch more errors, however.) If you respect the contract, your
code will be portable, however. If you don't, the standard has
decided that it will be undefined behavior; no error message is
required. And code which "happens to work" despite undefined
behavior is not portable. (This is no different that code which
depends on function arguments being evaluated in a specific
order.)
As mentioned in another thread that you have contributed to,
titled 'returning an iterator 'concept'', the actual class
behind the typedef'ed iterator could be anything that at the
least satisfies the iterator concept. If it in fact provides
more than that concept in implementation A, and a client uses
that extra functionality, then wouldn't the client code not
necessarily be portable to implementation B?

Yup. It's part of the basic philosophy of C++. If on my
machine, an int is 32 bits, and my code depends on this, then it
won't be portable to machines where ints are only 16 bits. If
on my machine, function arguments are evaluated from left to
right, and my code depends on this, then it won't be portable to
systems where this is not the case. (There is a difference, of
course. In the first case, I can count on the size of an int
being the same within a given implementation: the
implementation, and usually the platform, documents and
guarantees a specific size. So my code is guaranteed to work
for the implementation in question. In the case of order of
evaluation of arguments, the implementation doesn't guarantee
anything, and my code just happens to work, and may break with a
different set of optimization options. As far as I know,
variations in the implementation of iterators all fall into the
later category at present.)
 
P

Pete Becker

.

You've raised an interesting point. I don't think that the
intent is to require a typedef. Certainly in the requirements
section, all that is required is that container::iterator name a
type. Of hand, I would expect a nested class to be legal as
well.

That's covered under the as-if rule: there's no user-detectable
difference between a nested class named 'iterator' and a nested class
whose name is in the implementor's namespace combined with a typedef
that defines 'iterator' as an alias for that class's name. Both of
these definitions are okay, because standard-conforming user code won't
see any difference:

struct container
{
struct iterator {};
};

struct container
{
struct _Iterator {};
typedef _Iterator iterator;
};
 

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

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top