Title
Exactly when does size return end - begin?
Status
resolved
Section
[range.prim.size]
Submitter
Casey Carter

Created on 2020-01-07.00:00:00 last changed 45 months ago

Messages

Date: 2020-11-18.12:17:50

Proposed resolution:

This wording is relative to N4842.

  1. Modify [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 for make-unsigned-like which is defined in [ranges.syn]/1, not in [range.subrange].]

    -1- The name size denotes a customization point object ([customization.point.object]). The expression ranges::size(E) for some subexpression E with type T is expression-equivalent to:

    1. (1.1) — decay-copy(extent_v<T>) if T is an array type ([basic.compound]).

    2. (1.2) — Otherwise, if disable_sized_range<remove_cv_t<T>> ([range.sized]) is false:

    3. (1.?2.1) — Otherwise, if disable_sized_range<remove_cv_t<T>> ([range.sized]) is false and decay-copy(E.size()) if it is a valid expression and its type I isof integer-like type ([iterator.concept.winc]), decay-copy(E.size()).

    4. (1.?2.2) — Otherwise, if disable_sized_range<remove_cv_t<T>> is false and decay-copy(size(E)) if it is a valid expression and its type I isof integer-like type with overload resolution performed in a context that includes the declaration:

      template<class T> void size(Tauto&&) = delete;
      
      and does not include a declaration of ranges::size, decay-copy(size(E)).

    5. (1.3) — Otherwise, make-unsigned-like(ranges::end(E) - ranges::begin(E)) ([range.subrange][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> ([iterator.concept.sizedsentinel]) and forward_iterator<I>. However, E is evaluated only once.

    6. (1.4) — […]

Date: 2020-11-18.00:00:00

[ 2020-11-18 This was actually resolved by P2091R0 in Prague. Status changed: WP → Resolved. ]

Date: 2020-11-09.00:00:00

[ 2020-11-09 Approved In November virtual meeting. Status changed: Tentatively Ready → WP. ]

Date: 2020-01-25.00:00:00

[ 2020-01-25 Status set to Tentatively Ready after six positive votes on the reflector. ]

Date: 2020-01-15.18:30:02

The specification of ranges::size in [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.

History
Date User Action Args
2021-02-25 10:47:56adminsetstatus: wp -> resolved
2020-11-18 12:17:50adminsetmessages: + msg11618
2020-11-09 21:40:50adminsetmessages: + msg11559
2020-11-09 21:40:50adminsetstatus: ready -> wp
2020-01-25 12:29:23adminsetmessages: + msg10959
2020-01-25 12:29:23adminsetstatus: new -> ready
2020-01-14 14:01:29adminsetmessages: + msg10937
2020-01-07 00:00:00admincreate