This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.
ranges::empty has no semantic requirements for forward_rangesSection: 25.3.13 [range.prim.empty] Status: New Submitter: Hewill Kang Opened: 2024-03-30 Last modified: 2025-10-20
Priority: 3
View all issues with New status.
Discussion:
This is a small part of issues raised by already-closed P3156.
Currently,ranges::empty (25.3.13 [range.prim.empty]) is always a valid expression when applied
to forward_ranges, because even if it does not have .empty() or .size() we can always
check whether it is empty by comparing its begin() and end(), which is reflected in the
standard preference to use it to check whether a certain forward_range is empty,
such as in the Effects of split_view::find-next() (25.7.17.2 [range.split.view])
and cartesian_product_view::end() (25.7.33.2 [range.cartesian.view]).
In addition, MSVC-STL also uses ranges::empty in the implementation
of ranges::contains_subrange for the check.
However, unlike ranges::size, which has a sized_range concept to ensure semantics,
ranges::empty has no corresponding one. This makes it lack of time complexity guarantees and semantics
for the meaning of the returned value when using the bullets (2.2) and (2.3) of 25.3.13 [range.prim.empty]
to check emptiness.
Perhaps we need to add semantic requirements for ranges::empty, but this seems
inconsistent with the current wording as no other CPOs have.
Alternatively, maybe we could move bullets targeting forward_ranges to the very beginning so that
ranges::empty always has correct semantics with bool(ranges::begin(t) == ranges::end(t)) when
applied to forward_ranges.
[2025-10-20; Reflector poll.]
Set priority to 3 after reflector poll.
"This is the part of P3156 that is actually a defect.
We need to require ranges::empty to actually mean what we think it means.
Would be reasonable to add a sematic requirement to the range concept
that if ranges::empty(r) is well-formed then it does what it should do
(equal to bool(begin == end), has amortized constant complexity,
does not modify r, is not required to be valid after begin for non-forward)."
Proposed resolution: