3333. ranges::cbegin/ranges::cend, (and maybe ranges::crbegin/ranges::crend) are under-specified to allow rvalue-arrays

Section: 25.3.4 [range.access.cbegin], 25.3.5 [range.access.cend] Status: NAD Submitter: Christopher Di Bella Opened: 2019-11-06 Last modified: 2020-02-13

Priority: Not Prioritized

View all issues with NAD status.

Discussion:

The following should be ill-formed, but is not, likely due to decay-to-pointer or reference collapsing.

double x[321];
ranges::cbegin(std::move(x)); // should be ill-formed
ranges::cend(std::move(x));   // should be ill-formed

This might be a problem for ranges::crbegin and ranges::crend, but I haven't implemented any of rbegin, rend, crbegin, and crend to confirm as much.

[2020-02 Status to NAD on Thursday morning in Prague.]

Proposed resolution:

This wording is relative to N4835.

  1. Change 25.3.4 [range.access.cbegin] as indicated:

    -1- The name ranges::cbegin denotes a customization point object (16.3.3.3.5 [customization.point.object]). If tThe expression ranges::cbegin(E) for some subexpression E of type T is well-formed, then the expression ranges::cbegin(E) is expression-equivalent to:

    1. (1.1) — ranges::begin(static_cast<const T&>(E)) if E is an lvalue.

    2. (1.2) — Otherwise, ranges::begin(static_cast<const T&&>(E)).

  2. Change 25.3.5 [range.access.cend] as indicated:

    -1- The name ranges::cend denotes a customization point object (16.3.3.3.5 [customization.point.object]). If tThe expression ranges::cend(E) for some subexpression E of type T is well-formed, then the expression ranges::cend(E) is expression-equivalent to:

    1. (1.1) — ranges::end(static_cast<const T&>(E)) if E is an lvalue.

    2. (1.2) — Otherwise, ranges::end(static_cast<const T&&>(E)).