Title
std::ranges::repeat_view<T, IntegerClass>::iterator may be ill-formed
Status
c++23
Section
[range.repeat]
Submitter
Jiang An

Created on 2023-02-05.00:00:00 last changed 13 months ago

Messages

Date: 2023-02-13.11:31:32

Proposed resolution:

This wording is relative to n4928.

  1. Modify [ranges.syn], header <ranges> synopsis, as indicated:

    // […]
    namespace std::ranges {
      template<move_constructible W, semiregular Bound = unreachable_sentinel_t>
        requires see below(is_object_v<W> && same_as<W, remove_cv_t<W>> &&
                  (is-integer-like<Bound> || same_as<Bound, unreachable_sentinel_t>))
      class repeat_view;
    
  2. Modify [range.repeat.view] as indicated:

    namespace std::ranges {
      
      template<class T>
      concept integer-like-with-usable-difference-type =   //exposition only
        is-signed-integer-like<T> || (is-integer-like<T> && weakly_incrementable<T>);
    
      template<move_constructible W, semiregular Bound = unreachable_sentinel_t>
        requires (is_object_v<W> && same_as<W, remove_cv_t<W>> &&
                  (is-integer-likeinteger-like-with-usable-difference-type<Bound> || same_as<Bound, unreachable_sentinel_t>))
      class repeat_view {
        […]
      };
    }
    
  3. Modify [range.repeat.iterator] as indicated:

    namespace std::ranges {
      template<move_constructible W, semiregular Bound = unreachable_sentinel_t>
        requires (is_object_v<W> && same_as<W, remove_cv_t<W>> &&
                  (is-integer-likeinteger-like-with-usable-difference-type<Bound> || same_as<Bound, unreachable_sentinel_t>))
      class repeat_view<W, Bound>::iterator {
      private:
        using index-type =                  // exposition only
          conditional_t<same_as<Bound, unreachable_sentinel_t>, ptrdiff_t, Bound>;
        […]
      public:
        […]
        using difference_type = see belowconditional_t<is-signed-integer-like<index-type>,
            index-type,
            IOTA-DIFF-T(index-type)>;
        […]
      };
    }
    

    -?- If is-signed-integer-like<index-type> is true, the member typedef-name difference_type denotes index-type. Otherwise, it denotes IOTA-DIFF-T(index-type) ([range.iota.view]).

Date: 2023-02-13.00:00:00

[ 2023-02-13 Approved at February 2023 meeting in Issaquah. Status changed: Immediate → WP. ]

Date: 2023-02-10.01:18:32

[ Issaquah 2023-02-09; LWG ]

Move to Immediate for C++23

Date: 2023-02-09.00:00:00

[ 2023-02-09 Tim adds wording ]

We should reject types for which there is no usable difference type.

Date: 2023-02-05.00:00:00

[range.repeat.iterator] specifies difference_type as

using difference_type = conditional_t<is-signed-integer-like<index-type>,
  index-type,
  IOTA-DIFF-T(index-type)>;

which always instantiates IOTA-DIFF-T(index-type), and thus possibly makes the program ill-formed when index-type is an integer-class type (index-type is same as Bound in this case), because IOTA-DIFF-T(index-type) is specified to be iter_difference_t<index-type> which may be ill-formed ([range.iota.view]/1.1).

I think the intent is using index-type as-is without instantiating IOTA-DIFF-T when is-signed-integer-like<index-type> is true.

However, when Bound is an unsigned integer-class type, it's unclear which type should the difference type be, or whether repeat_view should be well-formed when the possibly intended IOTA-DIFF-T(Bound) is ill-formed.

History
Date User Action Args
2023-11-22 15:47:43adminsetstatus: wp -> c++23
2023-02-13 11:31:32adminsetmessages: + msg13400
2023-02-13 11:31:32adminsetstatus: immediate -> wp
2023-02-10 01:18:32adminsetmessages: + msg13327
2023-02-10 01:18:32adminsetstatus: new -> immediate
2023-02-09 14:22:23adminsetmessages: + msg13308
2023-02-09 14:22:23adminsetmessages: + msg13307
2023-02-05 00:00:00admincreate