3730. std::ranges::drop_view may have different size type from its underlying view

Section: 25.7.12.2 [range.drop.view] Status: New Submitter: Jiang An Opened: 2022-07-03 Last modified: 2022-07-17

Priority: 3

View other active issues in [range.drop.view].

View all other issues in [range.drop.view].

View all issues with New status.

Discussion:

The bodies of both overloads of drop_view<V>::size are specified as:

const auto s = ranges::size(base_);
const auto c = static_cast<decltype(s)>(count_);
return s < c ? 0 : s - c;

Given the return type is specified with auto, the actual return type is the promoted type of the size type of the underlying view, which may be different from the underlying size type (e.g. if the underlying size is unsigned short).

Note that take_view always has the same size type as its underlying view. So I think the difference on the size types is an oversight. On the other hand, the const used here seems redundant and inconsistent with other parts of the standard wording, although implementations may tend to use it.

[2022-07-08; Reflector poll]

Set priority to 3 after reflector poll.

"The PR is incorrect - integer-class types do not support mixed-signedess operations, so you have to cast one of the two first."

[2022-07-17; Daniel comments]

This issue should be resolved by keeping LWG 3739 and 3740 in mind.

Proposed resolution:

This wording is relative to N4910.

  1. Modify 25.7.12.2 [range.drop.view], class template drop_view synopsis, as indicated:

    [Drafting note: s and count_ usually have different types, but I think it's safe to perform comparison and subtraction, as count_ is non-negative as long as the behavior is well-defined.]

    […]
    constexpr auto size() requires sized_range<V> {
      const auto s = ranges::size(base_);
      const auto c = static_cast<decltype(s)>(count_);
      return static_cast<decltype(s)>(s < ccount_ ? 0 : s - ccount_);
    }
    
    constexpr auto size() const requires sized_range<const V> {
      const auto s = ranges::size(base_);
      const auto c = static_cast<decltype(s)>(count_);
      return static_cast<decltype(s)>(s < ccount_ ? 0 : s - ccount_);
    }
    […]