Title
Should range adaptor iterators only provide iterator_category when its difference_type is not an integer-class type?
Status
new
Section
[range.repeat.iterator][range.cartesian.iterator]
Submitter
Hewill Kang

Created on 2022-08-27.00:00:00 last changed 27 months ago

Messages

Date: 2023-02-07.12:12:38

Proposed resolution:

This wording is relative to n4917.

  1. 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-like<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>;
        const W* value_ = nullptr;          // exposition only
        index-type current_ = index-type(); // exposition only
    
        constexpr explicit iterator(const W* value, index-type b = index-type());   // exposition only
    
      public:
        using iterator_concept = random_access_iterator_tag;
        using iterator_category = random_access_iterator_tag;           // present only if difference_type
                                                                        // is an integral type
        using value_type = W;
        using difference_type = conditional_t<is-signed-integer-like<index-type>,
            index-type,
            IOTA-DIFF-T(index-type)>; 
        […]
      };
    }
    
  2. Modify [range.cartesian.iterator] as indicated:

    namespace std::ranges {
      template<input_range First, forward_range... Vs>
        requires (view<First> && ... && view<Vs>)
      template<bool Const>
      class cartesian_product_view<First, Vs...>::iterator {
      public:
        using iterator_category = input_iterator_tag;
        using iterator_concept  = see below;
        using value_type = tuple<range_value_t<maybe-const<Const, First>>,
          range_value_t<maybe-const<Const, Vs>>...>;
        using reference = tuple<range_reference_t<maybe-const<Const, First>>,
          range_reference_t<maybe-const<Const, Vs>>...>;
        using difference_type = see below;
        […]
      
        constexpr autoreference operator[](difference_type n) const
          requires cartesian-product-is-random-access<Const, First, Vs...>;
      
        […]
      };
    }
    

    […]

    constexpr autoreference operator[](difference_type n) const
      requires cartesian-product-is-random-access<Const, First, Vs...>;
    

    -24- Effects: return *((*this) + n);

Date: 2022-09-15.00:00:00

[ 2022-09-23; Reflector poll ]

Set priority to 3 after reflector poll.

Date: 2022-08-27.00:00:00

After P2259, the range adaptor' iterators only provide iterator_category member when the underlying range models forward_range, which is mainly based on the premise that all valid C++20 forward iterators meet the C++17 input iterator requirements.

However, this is not strictly correct. When the underlying range's difference_type is an integer-class type, its iterator does not conform Cpp17InputIterator.

Although iterator_traits<I>::iterator_category will still deduce the correct category in this case since these iterators have no reference member, it might be misleading to provide these incorrect member types.

Do we need to aggressively prohibit these iterators from providing iterator_category when their difference type is an integer-class type?

The proposed resolution makes repeat_view::iterator conditionally provide iterator_category, because it explicitly mentions IOTA-DIFF-T(index-type) in the definition of difference_type, which makes it consistent with LWG 3670.

It also removes the reference member type of cartesian_product_view::iterator, which prevents iterator_traits<I>::iterator_category from being aliased to its member iterator_category, so that iterator_traits<I>::iterator_category will not always be an input_iterator_tag when its difference_type is an integer-class type.

This is also consistent with other range adaptors, as none of them have a reference member type.

History
Date User Action Args
2022-09-23 15:44:07adminsetmessages: + msg12799
2022-09-03 16:19:34adminsetmessages: + msg12734
2022-08-27 00:00:00admincreate