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

### 3281. Conversion from `pair-like` types to `subrange` is a silent semantic promotion

Section: 24.5.4 [range.subrange] Status: C++20 Submitter: Eric Niebler Opened: 2019-09-10 Last modified: 2021-02-25

Priority: 1

View all other issues in [range.subrange].

View all issues with C++20 status.

Discussion:

Just because a `pair` is holding two iterators, it doesn't mean those two iterators denote a valid range. Implicitly converting such `pair-like` types to a `subrange` is dangerous and should be disallowed.

Suggested priority P1.

Implementation experience: range-v3's subrange lacks these constructors.

[2019-10 Priority set to 1 and status to LEWG after reflector discussion]

[2019-11 Status to Ready after LWG discussion Friday in Belfast.]

Proposed resolution:

This wording is relative to N4830.

1. Modify 24.5.4 [range.subrange] as indicated:

   >     namespace std::ranges {
   >     […]
   >       template<class T, class U, class V>
   >         concept pair-like-convertible-to = // exposition only
   >           !range<T> && pair-like<remove_reference_t<T>> &&
   >           requires(T&& t) {
   >             { get<0>(std::forward<T>(t)) } -> convertible_to<U>;
   >             { get<1>(std::forward<T>(t)) } -> convertible_to<V>;
   >           };
   >     […]
   >       template<input_or_output_iterator I, sentinel_for<I> S = I, subrange_kind K =
   >                sized_sentinel_for<S, I> ? subrange_kind::sized : subrange_kind::unsized>
   >         requires (K == subrange_kind::sized || !sized_sentinel_for<S, I>)
   >       class subrange : public view_interface<subrange<I, S, K>> {
   >       private:
   >         […]
   >       public:
   >         […]
   >         template<not-same-as<subrange> PairLike>
   >           requires pair-like-convertible-to<PairLike, I, S>
   >         constexpr subrange(PairLike&& r) requires (!StoreSize)
   >           : subrange{std::get<0>(std::forward<PairLike>(r)),
   >                      std::get<1>(std::forward<PairLike>(r))}
   >         {}
   >         template<pair-like-convertible-to<I, S> PairLike>
   >         constexpr subrange(PairLike&& r, make-unsigned-like-t(iter_difference_t<I>) n)
   >           requires (K == subrange_kind::sized)
   >           : subrange{std::get<0>(std::forward<PairLike>(r)),
   >                      std::get<1>(std::forward<PairLike>(r)), n}
   >         {}
   >       […]
   >       };
   >     […]
   >     }