iterator_traits

14 views
Skip to first unread message

Ian Lazarus

unread,
Aug 14, 2002, 4:32:35 PM8/14/02
to
Why is the struct "iterator_traits" defined? It appears to be redundant
since it requires that the iterator type declare the same typenames which it
does. For example, why should I write

std::iterator_traits<MyNamespace::MyIter>::difference_type

when I can more easily write

MyNamespace::MyIter::difference_type

I don't see what information or convenience iterator_traits provides.

Thanks


NotFound

unread,
Aug 14, 2002, 4:36:59 PM8/14/02
to
Ian Lazarus escribió:

>
> Why is the struct "iterator_traits" defined? It appears to be redundant
> since it requires that the iterator type declare the same typenames which it
> does. For example, why should I write
>
> std::iterator_traits<MyNamespace::MyIter>::difference_type
>
> when I can more easily write
>
> MyNamespace::MyIter::difference_type

You can't do this with pointers, but you can easily define
iterator_traits for pointers, and the standard library do this.

Regards.

Davlet Panech

unread,
Aug 14, 2002, 6:35:07 PM8/14/02
to
Ian Lazarus wrote:
>
> Why is the struct "iterator_traits" defined? It appears to be redundant
> since it requires that the iterator type declare the same typenames which it
> does. For example, why should I write
>
> std::iterator_traits<MyNamespace::MyIter>::difference_type
>
> when I can more easily write
>
> MyNamespace::MyIter::difference_type
>

With traits you could use things like

std::iterator_traits< int * >::difference_type

i.e., treat pointers as iterators.

Marc Cromme

unread,
Sep 29, 2002, 10:12:59 AM9/29/02
to


Consider the following:

You want to write a generic function which takes some iterator range
and computes something inside which requires for example the value type.

Now you define for example

template<class Iterator>
Iterator::value_type somefunction(Iterator first, Iterator last)
{
Iterator::value_type mean = (*first + *last)/2.0;
return mean;
}

Looks OK ??? Pointers are iterators ??? Yep.
But your compiler will choke on this if you call it like this

T* first;
T* second;
T answer = somefunction(first, second);

Why?? Because It does not know how to apply the :: scope operator on a
given pointer type T* (You do fine using dereferencing
like *first, but what is it's type ??? You can not know...)

So, the compiler needs som help in doing the obvious (for humans obvious
at least..). And the only way to do it is through an indirection over the
traits classes.

The trick is using

typename iterator_traits<Iterator>::value_type mean = ...

because a suitable specialization

template <class T>
struct iterator_traits<T*>
{
typedef T value_type
....


let the compiler know what the value type of a T* is, and the most general
template struct iterator_traits points of course to the
Iterator::value_type as you would like to use it directly.


The reason is also to be able to treat ordinary pointers as iterators in
genetic algorithms.

For details, see please

"Generic Programming and the STL" Matthew H. Austern,
ISBN 0-201-30956-4

a really good book on this topic.


Cheers, Marc Cromme

Reply all
Reply to author
Forward
0 new messages