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.

### 3535. `join_view::iterator::iterator_category` and `::iterator_concept` lie

Section: 26.7.14.3 [range.join.iterator] Status: WP Submitter: Casey Carter Opened: 2021-03-16 Last modified: 2021-10-14

Priority: 2

View all other issues in [range.join.iterator].

View all issues with WP status.

Discussion:

Per 26.7.14.3 [range.join.iterator]/1, `join_view::iterator::iterator_concept` denotes `bidirectional_iterator_tag` if `ref-is-glvalue` is `true` and `Base` and `range_reference_t<Base>` each model `bidirectional_range`. Similarly, paragraph 2 says that `join_view::iterator::iterator_category` is present if `ref-is-glvalue` is `true`, and denotes `bidirectional_iterator_tag` if the categories of the iterators of both `Base` and `range_reference_t<Base>` derive from `bidirectional_iterator_tag`.

However, the constraints on the declarations of `operator--` and `operator--(int)` in the synopsis that immediately precedes paragraph 1 disagree. Certainly they also consistently require `ref-is-glvalue && bidirectional_range<Base> && bidirectional_range<range_reference_t<Base>>`, but they additionally require `common_range<range_reference_t<Base>>`. So as currently specified, this iterator sometimes declares itself to be bidirectional despite not implementing `--`. This is not incorrect for iterator_concept — recall that `iterator_concept` is effectively an upper bound since the concepts require substantial syntax — but slightly misleading. It is, however, very much incorrect for `iterator_category` which must not denote a type derived from a tag that corresponds to a stronger category than that iterator implements.

It's worth pointing out, that LWG 3313 fixed the constraints on `operator--()` and `operator--(int)` by adding the `common_range` requirements, but failed to make a consistent change to the definitions of `iterator_concept` and `iterator_category`.

[2021-04-04; Daniel comments]

The below proposed wording can be compared as being based on N4885.

[2021-04-20; Reflector poll]

Priority set to 2.

[2021-06-23; Reflector poll]

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

[2021-10-14 Approved at October 2021 virtual plenary. Status changed: Voting → WP.]

Proposed resolution:

This wording is relative to the post-2021-February-virtual-meeting working draft.

1. Modify 26.7.14.3 [range.join.iterator] as indicated:

   > -1- `iterator::iterator_concept` is defined as follows:

   > 1. (1.1) — If `ref-is-glvalue` is `true`, and `Base` and `range_reference_t<Base>` each models `bidirectional_range`, and `range_reference_t<Base>` models both `bidirectional_range` and `common_range`, then `iterator_concept` denotes `bidirectional_iterator_tag`.

   > 2. […]

   > […]

   > -2- The member typedef-name `iterator_category` is defined if and only if `ref-is-glvalue` is `true`, `Base` models `forward_range`, and `range_reference_t<Base>` models `forward_range`. In that case, `iterator::iterator_category` is defined as follows:

   > 1. (2.1) — Let `OUTERC` denote `iterator_traits<iterator_t<Base>>::iterator_category`, and let `INNERC` denote `iterator_traits<iterator_t<range_reference_t<Base>>>::iterator_category`.

   > 2. (2.2) — If `OUTERC` and `INNERC` each model `derived_from<bidirectional_iterator_tag>`, and `range_reference_t<Base>` models `common_range`, `iterator_category` denotes `bidirectional_iterator_tag`.

   > 3. […]