7

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?

TemplateRex
  • 69,038
  • 19
  • 164
  • 304
  • 2
    I found no uses in the original SGI STL or in the C++ standard. Probably provided as a means for the language user to use it, not the standard library. – Rapptz Feb 17 '14 at 10:27
  • 1
    You may find its declared type interesting in an iterator who's template type is specialized by `` It is still `T*`, but `T` everywhere else loses the `*`. – WhozCraig Feb 17 '14 at 10:51
  • @WhozCraig tnx good point, but if I would just declare `using pointer = void` for my own iterator, where could I get bitten? – TemplateRex Feb 17 '14 at 10:53
  • It is used by reverse_iterator to find the return type of operator-> for instance. – Marc Glisse Feb 17 '14 at 10:53
  • That I cannot tell you. Is your iterator an output iterator ? If so, the standard says it can be defined as `void`, otherwise it shall be defined properly. (again, this is for `iterator_traits` so I can't comment on boost's template, as i'm unfamiliar with it). – WhozCraig Feb 17 '14 at 10:58
  • 1
    Note that in C++11 `reference` is mostly useless since you can look at `decltype(*it)`. Looking at `it->` seems harder :-( – Marc Glisse Feb 17 '14 at 11:02
  • @MarcGlisse My proxy iterator is bidirectional, and if I define `pointer` somehow, `reverse_iterator` can extract it so as to comply with the iterator requirements. But I can't find any actual *usage* of the `pointer` type in any standard algorithm. The default is `T*`, output iterators can set it to `void`, and as long as you don't need `operator->` (which I don't) there seems no harm in setting it to `void` or any other arbitrary type. – TemplateRex Feb 17 '14 at 11:34

1 Answers1

5

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.

TemplateRex
  • 69,038
  • 19
  • 164
  • 304