size
return end - begin
?Section: 25.3.10 [range.prim.size] Status: Resolved Submitter: Casey Carter Opened: 2020-01-07 Last modified: 2021-02-25
Priority: 0
View all issues with Resolved status.
Discussion:
The specification of ranges::size
in 25.3.10 [range.prim.size] suggests that bullet 1.3
("Otherwise, make-unsigned-like(ranges::end(E) - ranges::begin(E)) ...")
only applies
when disable_sized_range<remove_cv_t<T>>
is true
. This is not the
design intent, but the result of an erroneous attempt to factor out the common
"disable_sized_range
is false
" requirement from the member and non-member size
cases in bullets 1.2.1 and 1.2.2 that occurred between P0896R3 and
P0896R4. The intended design has always been that a range with
member or non-member size
with the same syntax but different semantics may opt-out of being
sized by specializing disable_sized_range
. It has never been intended that arrays or ranges
whose iterator and sentinel model sized_sentinel_for
be able to opt out of being sized via
disable_sized_range
. disable_sized_sentinel_for
can/must be used to opt out in the
latter case so that library functions oblivious to the range type that operate on the iterator and
sentinel of such a range will avoid subtraction.
[2020-01-25 Status set to Tentatively Ready after six positive votes on the reflector.]
[2020-11-09 Approved In November virtual meeting. Status changed: Tentatively Ready → WP.]
[2020-11-18 This was actually resolved by P2091R0 in Prague. Status changed: WP → Resolved.]
Proposed resolution:
This wording is relative to N4842.
Modify 25.3.10 [range.prim.size] as indicated:
[Drafting note: There are drive-by changes here to (1) avoid introducing unused type placeholders, (2) avoid reusing "
T
" as both the type of the subexpression and the template parameter of the poison pill, and (3) fix the cross-reference formake-unsigned-like
which is defined in [ranges.syn]/1, not in [range.subrange].]
-1- The name
size
denotes a customization point object (16.3.3.3.5 [customization.point.object]). The expressionranges::size(E)
for some subexpressionE
with typeT
is expression-equivalent to:
(1.1) —
decay-copy(extent_v<T>)
ifT
is an array type (6.8.4 [basic.compound]).
(1.2) — Otherwise, ifdisable_sized_range<remove_cv_t<T>>
(25.4.3 [range.sized]) isfalse
:(1.?
2.1) — Otherwise, ifdisable_sized_range<remove_cv_t<T>>
(25.4.3 [range.sized]) isfalse
anddecay-copy(E.size())
if itis a valid expressionand its typeof integer-like type (24.3.4.4 [iterator.concept.winc]),I
isdecay-copy(E.size())
.(1.?
2.2) — Otherwise, ifdisable_sized_range<remove_cv_t<T>>
isfalse
anddecay-copy(size(E))
if itis a valid expressionand its typeof integer-like type with overload resolution performed in a context that includes the declaration:I
isand does not include a declaration oftemplate<class T>void size(Tauto&&) = delete;ranges::size
,decay-copy(size(E))
.
(1.3) — Otherwise, make-unsigned-like(ranges::end(E) - ranges::begin(E))
(25.5.4 [range.subrange]25.2 [ranges.syn]) if it is a valid
expression and the types I
and S
of
ranges::begin(E)
and ranges::end(E)
(respectively) model both
sized_sentinel_for<S, I>
(24.3.4.8 [iterator.concept.sizedsentinel]) and
forward_iterator<I>
. However, E
is evaluated only once.
(1.4) — […]