This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of CD1 status.

### 445. iterator_traits::reference unspecified for some iterator categories

Section: 23.3.2.3 [iterator.traits] Status: CD1 Submitter: Dave Abrahams Opened: 2003-12-09 Last modified: 2016-01-28

Priority: Not Prioritized

View all other issues in [iterator.traits].

View all issues with CD1 status.

Discussion:

The standard places no restrictions at all on the reference type of input, output, or forward iterators (for forward iterators it only specifies that *x must be value_type& and doesn't mention the reference type). Bidirectional iterators' reference type is restricted only by implication, since the base iterator's reference type is used as the return type of reverse_iterator's operator*, which must be T& in order to be a conforming forward iterator.

Here's what I think we ought to be able to expect from an input or forward iterator's reference type R, where a is an iterator and V is its value_type

- *a is convertible to R
- R is convertible to V
- static_cast<V>(static_cast<R>(*a)) is equivalent to static_cast<V>(*a)

A mutable forward iterator ought to satisfy, for x of type V:

          { R r = *a; r = x; } is equivalent to *a = x;

I think these requirements capture existing container iterators (including vector<bool>'s), but render istream_iterator invalid; its reference type would have to be changed to a constant reference.

(Jeremy Siek) During the discussion in Sydney, it was felt that a simpler long term solution for this was needed. The solution proposed was to require `reference` to be the same type as `*a` and `pointer` to be the same type as `a->`. Most iterators in the Standard Library already meet this requirement. Some iterators are output iterators, and do not need to meet the requirement, and others are only specified through the general iterator requirements (which will change with this resolution). The sole case where there is an explicit definition of the reference type that will need to change is `istreambuf_iterator` which returns `charT` from `operator*` but has a reference type of `charT&`. We propose changing the reference type of `istreambuf_iterator` to `charT`.

The other option for resolving the issue with `pointer`, mentioned in the note below, is to remove `pointer` altogether. I prefer placing requirements on `pointer` to removing it for two reasons. First, `pointer` will become useful for implementing iterator adaptors and in particular, `reverse_iterator` will become more well defined. Second, removing `pointer` is a rather drastic and publicly-visible action to take.

The proposed resolution technically enlarges the requirements for iterators, which means there are existing iterators (such as `istreambuf_iterator`, and potentially some programmer-defined iterators) that will no longer meet the requirements. Will this break existing code? The scenario in which it would is if an algorithm implementation (say in the Standard Library) is changed to rely on `iterator_traits::reference`, and then is used with one of the iterators that do not have an appropriately defined `iterator_traits::reference`.

The proposed resolution makes one other subtle change. Previously, it was required that output iterators have a `difference_type` and `value_type` of `void`, which means that a forward iterator could not be an output iterator. This is clearly a mistake, so I've changed the wording to say that those types may be `void`.

Proposed resolution:

In 23.3.2.3 [iterator.traits], after:

> be defined as the iterator's difference type, value type and iterator category, respectively.

add

> In addition, the types

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

> must be defined as the iterator's reference and pointer types, that is, the same type as the type of `*a` and `a->`, respectively.

In 23.3.2.3 [iterator.traits], change:

> In the case of an output iterator, the types

>     iterator_traits<Iterator>::difference_type
>     iterator_traits<Iterator>::value_type

> are both defined as `void`.

to:

> In the case of an output iterator, the types

>     iterator_traits<Iterator>::difference_type
>     iterator_traits<Iterator>::value_type
>     iterator_traits<Iterator>::reference
>     iterator_traits<Iterator>::pointer

> may be defined as `void`.

In 23.6.4 [istreambuf.iterator], change:

>     typename traits::off_type, charT*, charT&>

to:

>     typename traits::off_type, charT*, charT>

[ Redmond: there was concern in Sydney that this might not be the only place where things were underspecified and needed to be changed. Jeremy reviewed iterators in the standard and confirmed that nothing else needed to be changed. ]