3183. Normative permission to specialize Ranges variable templates

Section: 24.3.4.8 [iterator.concept.sizedsentinel] Status: C++20 Submitter: Casey Carter Opened: 2019-01-14 Last modified: 2021-02-25

Priority: 0

View all issues with C++20 status.

Discussion:

P0896R4 "The One Ranges Proposal" added boolean variable templates std::disable_sized_sentinel and std::ranges::disable_sized_range which users are intended to specialize to false for program-defined Iterator-Sentinel pairs / Range types which meet the syntax but do not model the semantics of the SizedSentinel / SizedRange concepts, respectively. Specializing these traits allows the use of such types with the library which would otherwise treat them as if they model SizedSentinel / SizedRange. The wording in P0896R4 failed, however, to provide normative permission to specialize these variable templates as is required by 16.4.5.2.1 [namespace.std] after the application of P0551R3.

Furthermore, 16.4.5.2.1 [namespace.std] notably does not require that program-defined specializations of standard library variable templates meet the requirements on the primary template (as is the case for class templates) or indeed any requirements. P0896R4 also added the enable_view variable template which is used to explicitly opt in or out of the View concept 25.4.4 [range.view] when the default chosen by the heuristic is incorrect. P0896R4 did include normative permission to specialize enable_view, but the wording does not place sufficient requirements on such user specializations so as to make them usable by the View concept definition. Specializations must be required to be usable as constant expressions of type bool to avoid hard errors in the concept.

[2019-02-03 Priority to 0 and Status to Tentatively Ready after five positive votes on the reflector.]

Proposed resolution:

This wording is relative to N4791.

[Drafting Note: This wording uses the recently-defined core language term "usable in constant expressions" from 7.7 [expr.const] paragraph 3 which may be unfamiliar to reviewers.]

  1. Change 24.3.4.8 [iterator.concept.sizedsentinel] as follows:

    […]

    (2.2) — If −N is representable by iter_difference_t<I>, then i - s is well-defined and equals −N.

    -?- Pursuant to 16.4.5.2.1 [namespace.std], users may specialize disable_sized_sentinel for cv-unqualified non-array object types S and I at least one of which is a program-defined type. Such specializations shall be usable in constant expressions (7.7 [expr.const]) and have type const bool.

    3 [Note: disable_sized_sentinel allows use of sentinels and iterators with the library that satisfy but do not in fact model SizedSentinel.—end note]

    […]

  2. Add an index entry for disable_sized_sentinel that points to [iterator.concepts.sizedsentinel].

  3. Change 25.4.3 [range.sized] as follows:

    […]

    3 [Note: The complexity requirement for the evaluation of ranges::size is non-amortized, unlike the case for the complexity of the evaluations of ranges::begin and ranges::end in the Range concept.—end note]

    -?- Pursuant to 16.4.5.2.1 [namespace.std], users may specialize disable_sized_range for cv-unqualified program-defined types. Such specializations shall be usable in constant expressions (7.7 [expr.const]) and have type const bool.

    4 [Note: disable_sized_range allows use of range types with the library that satisfy but do not in fact model SizedRange.—end note]

  4. Add an index entry for disable_sized_range that points to 25.4.3 [range.sized].

  5. Change 25.4.4 [range.view] as follows:

    […]

    5 Pursuant to 16.4.5.2.1 [namespace.std], users may specialize enable_view to true for cv-unqualified program-defined types which model View, and false for types which do not. Such specializations shall be usable in constant expressions (7.7 [expr.const]) and have type const bool.