Question

The std::iterator_traits class template defines 5 nested types: iterator_category, value_type, difference_type, pointer and reference. Browsing the sources of the <algorithm> header of both libc++ and libstdc++, one can see many uses of value_type, difference_type and iterator_category, but only one for reference (inside std::iter_swap) and none for pointer.

My application uses a hand-built proxy iterator / proxy reference pair. I want to transition to using the Boost iterator_facade which lets me configure the reference type from the default T& to an arbitrary type, but not so for the pointer type which is T* by default. I want to avoid being bitten by some deeply hidden use of the nested pointer type.

Note: the iterator is a proxy for a builtin type without nested members, so I do not need compatibility with operator-> (for which the return type would be pointer).

Question: what use cases are there in the Standard Library for the nested type pointer inside iterator_traits?

Was it helpful?

Solution

In contrast to the first three types iterator_category, value_type and difference_type (which are heavily used by the standard algorithms for tag dispatching to efficient versions depending on the iterator capabilities) the last two types pointer and reference inside iterator_traits appear not to be used by any algorithms but are used to define compliance with the iterator requirements.

24.2.1 In general [iterator.requirements.general]

1 [..] All iterators i for which the expression (*i).m is well-defined, support the expression i->m with the same semantics as (*i).m. [...]

24.4.1 Iterator traits [iterator.traits]

[...] In addition, the types

 iterator_traits<Iterator>::reference
 iterator_traits<Iterator>::pointer 

shall be defined as the iterator’s reference and pointer types, that is, for an iterator object a, the same type as the type of *a and a->, respectively. [...]

The default values T* and T& for pointer and reference of course satisfy the iterator requirements. Regarding proxy references, the Boost.Iterator documentation specifies

The reference type of a readable iterator (and today's input iterator) need not in fact be a reference, so long as it is convertible to the iterator's value_type. When the value_type is a class, however, it must still be possible to access members through operator->. Therefore, an iterator whose reference type is not in fact a reference must return a proxy containing a copy of the referenced value from its operator->.

The return types for iterator_facade's operator-> and operator[] are not explicitly specified. Instead, those types are described in terms of a set of requirements, which must be satisfied by the iterator_facade implementation.

Conclusion: as long as a proxy iterator does not require accessing members of its underlying value_type through .m or ->m, one does not need to worry about the pointer type inside iterator_traits, and even if one does use proxy iterators, boost::iterator_facade will do the right thing.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top