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

### 3783. `views::common` may not be a range adaptor object

Section: 25.5.5.1 [common.iterator], 25.5.5.6 [common.iter.cmp] Status: New Submitter: Hewill Kang Opened: 2022-09-18 Last modified: 2022-10-12

Priority: 3

View all other issues in [common.iterator].

View all issues with New status.

Discussion:

P2325R3 makes `input_or_output_iterator` no longer require `default_initializable`, which means that the template parameter `I` of `common_iterator` no longer requires `default_initializable`.

In this case, since `common_iterator` itself cannot be default-constructed, it can never be a valid sentinel even if it can be compared to itself. Furthermore, this also makes `views::common` return a non-`range` even if it is well-formed (online example):

>     #include <ranges>
>     #include <vector>

>     int main() {
>       std::vector<int> v;
>       auto r = std::views::counted(std::back_inserter(v), 3);
>       auto cr = r | std::views::common;
>       static_assert(std::ranges::range<decltype(cr)>); // failed
>     }

which causes `views::common` to be unable to convert a `range` into a `view`, making it not a valid range adaptor.

I think `common_iterator` should always be `default_initializable`, which makes it eligible to be a legitimate sentinel.

The proposed resolution provides a default constructor for `common_iterator` when `I` is not `default_initializable`, in which case constructs the `variant` with an alternative type of `S`.

[2022-09-28; Reflector poll]

Set priority to 3 after reflector poll.

"The P/R means that sometimes the variant containers an iterator and sometimes contains a sentinel, depending on whether the iterator is default constructible. Always constructing a sentinel would be more consistent."

Proposed resolution:

This wording is relative to N4917.

1. Modify 25.5.5.1 [common.iterator], class template `common_iterator` synopsis, as indicated:

   >     namespace std {
   >       template<input_or_output_iterator I, sentinel_for<I> S>
   >         requires (!same_as<I, S> && copyable<I>)
   >       class common_iterator {
   >       public:
   >         constexpr common_iterator() requires default_initializable<I> = default;
   >         constexpr common_iterator();
   >         […]
   >       };
   >       […]
   >     }

2. Modify 25.5.5.3 [common.iter.const] as indicated:

   >     constexpr common_iterator();

   > > -?- Effects: Initializes `v_` as if by `v_{in_place_type<S>}`.

   >     constexpr common_iterator(I i);

   > > -1- Effects: Initializes `v_` as if by `v_{in_place_type<I>, std::move(i)}`.