Title
Conversion from pair-like types to subrange is a silent semantic promotion
Status
c++20
Section
[range.subrange]
Submitter
Eric Niebler

Created on 2019-09-10.00:00:00 last changed 45 months ago

Messages

Date: 2019-11-08.15:56:47

Proposed resolution:

This wording is relative to N4830.

  1. Modify [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}
        {}
      […]
      };
    […]
    }
    
Date: 2019-11-08.15:56:47

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

Date: 2019-10-07.02:21:30

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

Date: 2019-09-10.00:00:00

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.

History
Date User Action Args
2021-02-25 10:48:01adminsetstatus: wp -> c++20
2020-02-24 16:02:59adminsetstatus: voting -> wp
2020-01-17 04:54:50adminsetstatus: ready -> voting
2019-11-08 15:56:47adminsetmessages: + msg10807
2019-11-08 15:56:47adminsetstatus: lewg -> ready
2019-10-07 02:21:30adminsetmessages: + msg10684
2019-10-07 02:21:30adminsetstatus: new -> lewg
2019-09-15 14:48:22adminsetmessages: + msg10633
2019-09-10 00:00:00admincreate