David Abrahams
Raoul Gough
writes: [snip] I guess in an ideal world, we would have something like this:
template<typename T> struct handle_traits { typedef typename T::value_type value_type; typedef typename T::pointer_type pointer_type; typedef typename T::reference_type reference_type; };
template<typename T> struct iterator_traits : public handle_traits<T> { typedef typename T::iterator_category iterator_category; typedef typename T::difference_type difference_type; };
I don't see why that's preferable to what we have now with referent.
After realising that an iterator is just a kind of handle that supports movement (according to its iterator_category) I figured that the traits subclassing was an accurate representation. Doing it this way, with handle_traits more general than iterator_traits (and at least as visible to client code) it seems like a good central repository for the type information. If you only want info about operator*() then you can use handle_traits<T> without knowing whether T is really an iterator. It also helps to document the requirements. For example, a valid handle class T requires handle_traits<T> and an operator*() that returns handle_traits<T>::reference_type. A valid iterator T is a handle that additionally has iterator_traits<T>, and movement functions dependant on iterator_category. indirect_iterator<T> requires that T is a valid iterator and that iterator_traits<T>::value_type is a valid handle. Seems neat to me, but who would have designed std::iterator_traits that way back then :-) -- Raoul Gough "Let there be one measure for wine throughout our kingdom, and one measure for ale, and one measure for corn" - Magna Carta