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

### 3660. `iterator_traits<common_iterator>::pointer` should conform to §[iterator.traits]

Section: 23.5.4.2 [common.iter.types] Status: WP Submitter: Casey Carter Opened: 2022-01-20 Last modified: 2022-02-10

Priority: Not Prioritized

View all issues with WP status.

Discussion:

23.3.2.3 [iterator.traits]/1 says:

> […] In addition, the types

> >     iterator_traits<I>::pointer
> >     iterator_traits<I>::reference

> shall be defined as the iterator's pointer and reference types; that is, for an iterator object `a` of class type, the same type as `decltype(a.operator->())` and `decltype(*a)`, respectively. The type `iterator_traits<I>::pointer` shall be `void` for an iterator of class type `I` that does not support `operator->`. […]

23.5.4.2 [common.iter.types]/1 slightly contradicts this:

> The nested typedef-names of the specialization of `iterator_traits` for `common_iterator<I, S>` are defined as follows.

> 1. […]

> 2. (1.3) — If the expression `a.operator->()` is well-formed, where `a` is an lvalue of type `const common_iterator<I, S>`, then `pointer` denotes the type of that expression. Otherwise, `pointer` denotes `void`.

"The type of `a.operator->()`" is not necessarily the same as `decltype(a.operator->())`: when the expression is an lvalue or xvalue of type `T`, "the type of `a.operator->()`" is `T` but `decltype(a.operator->())` is either `T&` or `T&&`. An implementation therefore cannot conform to the requirements of both cited paragraphs for some specializations of `common_iterator`.

The most likely explanation for this contradiction is that the writer of the phrase "type of `a.operator->()`" was not cognizant of the difference in meaning and intended to actually write `decltype(a.operator->())`.

[2022-01-30; Reflector poll]

Set status to Tentatively Ready after five votes in favour during reflector poll.

[2022-02-10 Approved at February 2022 virtual plenary. Status changed: Tentatively Ready → WP.]

Proposed resolution:

This wording is relative to N4901.

> [Drafting Note: The wording change below includes an additional drive-by fix that ensures that the last sentence "Otherwise, `pointer` denotes `void`" cannot be misinterpreted (due to the leading "If") to apply also for a situation when the outcome of the expression `a.operator->()` for a non-`const` `common_iterator<I, S>` is reflected upon.]

1. Modify 23.5.4.2 [common.iter.types] as indicated:

   > -1- The nested typedef-names of the specialization of `iterator_traits` for `common_iterator<I, S>` are defined as follows.

   > 1. […]

   > 2. (1.3) — Let `a` denote an lvalue of type `const common_iterator<I, S>`. If the expression `a.operator->()` is well-formed, where `a` is an lvalue of type `const common_iterator<I, S>`, then `pointer` denotes `decltype(a.operator->())`the type of that expression. Otherwise, `pointer` denotes `void`.