common_iterator
and counted_iterator
' operator-
are missing cast to return typeSection: 24.5.5.6 [common.iter.cmp], 24.5.7.5 [counted.iter.nav] Status: New Submitter: Hewill Kang Opened: 2022-08-01 Last modified: 2022-08-23
Priority: 3
View all issues with New status.
Discussion:
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.
[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."
Proposed resolution:
This wording is relative to N4910.
Modify 24.5.5.6 [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:
-6- Returns:x.v_.valueless_by_exception()
andy.v_.valueless_by_exception()
are eachfalse
.0
ifi
andj
are each1
, and otherwisestatic_cast<iter_difference_t<I2>>(
get<i>(x.v_) - get<j>(y.v_)
)
, wherei
isx.v_.index()
andj
isy.v_.index()
.
Modify 24.5.7.5 [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:
-14- Effects: Equivalent to:x
andy
refer to elements of the same sequence (24.5.7.1 [counted.iterator]).return static_cast<iter_difference_t<I2>>(y.length - x.length);