Title
common_iterator and counted_iterator' operator- are missing cast to return type
Status
new
Section
[common.iter.cmp][counted.iter.nav]
Submitter
Hewill Kang

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

Messages

Date: 2022-08-23.15:25:16

Proposed resolution:

This wording is relative to N4910.

  1. Modify [common.iter.cmp] as indicated:

    template<sized_sentinel_for<I> I2, sized_sentinel_for<I> S2>
      requires sized_sentinel_for<S, I2>
    friend constexpr iter_difference_t<I2> operator-(
      const common_iterator& x, const common_iterator<I2, S2>& y);
    

    -5- Preconditions: x.v_.valueless_by_exception() and y.v_.valueless_by_exception() are each false.

    -6- Returns: 0 if i and j are each 1, and otherwise static_cast<iter_difference_t<I2>>(get<i>(x.v_) - get<j>(y.v_)), where i is x.v_.index() and j is y.v_.index().

  2. Modify [counted.iter.nav] as indicated:

    template<common_with<I> I2>
      friend constexpr iter_difference_t<I2> operator-(
        const counted_iterator& x, const counted_iterator<I2>& y);
    

    -13- Preconditions: x and y refer to elements of the same sequence ([counted.iterator]).

    -14- Effects: Equivalent to: return static_cast<iter_difference_t<I2>>(y.length - x.length);

Date: 2022-08-15.00:00:00

[ 2022-08-23; Reflector poll ]

Set priority to 3 after reflector poll.

"I think common_iterator should reject iterators with integer-class difference types since it can't possibly achieve the design intent of adapting them to Cpp17Iterators, so this issue should only affect counted_iterator."

"If the difference types of I and I2 are different then the operator- can't be used to model sized_sentinel_for, since i - i2 and i2 - i would have different types. Providing operator- under such circumstances seems to be of dubious value."

Date: 2022-08-07.10:52:06

Both common_iterator and counted_iterator explicitly specify that the return type of their operator- is iter_difference_t<I2>, however, given that the calculated type may be iter_difference_t<I>, we should do an explicit conversion here since the latter is not necessarily implicitly convertible to the former:

#include <ranges>

struct Y;

struct X {
  X(Y);
  using difference_type =
#ifdef __GNUC__
  std::ranges::__detail::__max_diff_type;
#elif defined(_MSC_VER)
  std::_Signed128;
#endif
  int& operator*() const;
  X& operator++();
  void operator++(int);
};

struct Y {
  using difference_type = std::ptrdiff_t;
  int& operator*() const;
  Y& operator++();
  void operator++(int);
};

int main() {
  std::counted_iterator<Y> y;
  return std::counted_iterator<X>(y) - y; // hard error in stdlibc++ and MSVC-STL
}

Daniel:

This issue shouldn't we voted until a decision for LWG 3749 has been made, because the first part of it overlaps with LWG 3749's second part.

History
Date User Action Args
2022-08-23 15:25:16adminsetmessages: + msg12704
2022-08-07 09:35:46adminsetmessages: + msg12668
2022-08-01 00:00:00admincreate