Title
Constant expression `ranges::size(r)` Constraints and Mandates in [simd]
Status
new
Section
[simd]
Submitter
Lénárd Szolnoki

Created on 2025-10-10.00:00:00 last changed 1 week ago

Messages

Date: 2025-10-22.12:32:36

Proposed resolution:

This wording is relative to N5014.

  1. Modify [simd.ctor] as indicated:

    template<class R, class... Flags>
      constexpr basic_vec(R&& r, flags<Flags...> = {});
    template<class R, class... Flags>
      constexpr basic_vec(R&& r, const mask_type& mask, flags<Flags...> = {});
    

    -12- Let `mask` be `mask_type(true)` for the overload with no `mask` parameter.

    -13- Constraints:

    1. (13.1) — `R` models `ranges::contiguous_range` and `ranges::sized_range`, and

    2. (13.2) — ranges::size(r) == size() is a constant expression, and evaluates to `true`.

    3. (13.3) — `ranges::size(r)` is equal to `size()`.

    […]
    template<class R, class... Ts>
      basic_vec(R&& r, Ts...) -> see below;
    

    -17- Constraints:

    1. (17.1) — `R` models `ranges::contiguous_range` and `ranges::sized_range`, and.

    2. (17.2) — `ranges::size(r)` is a constant expression.

    -18- Remarks: The deduced type is equivalent to vec<ranges::range_value_t<R>, ranges::size(r)>.

  2. Modify [simd.loadstore] as indicated:

    template<class V = see below, ranges::contiguous_range R, class... Flags>
      requires ranges::sized_range<R>
      constexpr V unchecked_load(R&& r, flags<Flags...> f = {});
    […]
    template<class V = see below, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags>
      constexpr V unchecked_load(I first, S last, const typename V::mask_type& mask,
                                 flags<Flags...> f = {});
    

    -1- Let […]

    -2- Mandates: If ranges::size(r) >= V::size() is a constant expression then `ranges::size(r)` ≥ `V::size()`it evaluates to `true`.

Date: 2025-10-15.00:00:00

[ 2025-10-22; Reflector poll. ]

Set priority to P3 after reflector poll.

General preference on considering this NAD, and instead clarifying that operations on integer-class should produce constant expressions.

Date: 2025-10-10.00:00:00

Various Constraints and Mandates in [simd] are conditioned on `ranges::size(r)`, assuming that subsequent operations on the result are also constant expression. This is not a given, since `ranges::size(r)` is allowed to return an integer-class type, and it is not mandated that operations on integer-class types are usable in constant expressions.

In particular:

  1. [simd.ctor] p13:

    Constraints:

    • `R` models `ranges::contiguous_range` and `ranges::sized_range`,

    • `ranges::size(r)` is a constant expression, and

    • `ranges::size(r)` is equal to `size()`.

    Here `ranges::size(r) == size()` might not be a constant expression, even when `ranges::size(r)` is. Operations that are not accounted for:

    • Possible conversion from `range::size(r)` to simd-size-type.

    • Possible operator overloading on ==.

  2. [simd.ctor] p17+18:

    Constraints:

    • `R` models `ranges::contiguous_range` and `ranges::sized_range`, and

    • `ranges::size(r)` is a constant expression

    Remarks: The deduced type is equivalent to vec<ranges::range_value_t<R>, ranges::size(r)>.

    Here the second constraint is simply redundant, if failure to form the type is in the immediate context. If we want to type it out in the constraints then we should account for conversion to simd-size-type and narrowing.

  3. [simd.loadstore] p2:

    Mandates: If `ranges::size(r)` is a constant expression then `ranges::size(r)` ≥ `V::size()`.

    Here ranges::size(r) >= V::size() might not be a constant expression, even when `ranges::size(r)` is. It is unclear why a mathematical operator symbol is used here (and further down in the preconditions).

History
Date User Action Args
2025-10-22 12:32:36adminsetmessages: + msg15340
2025-10-12 09:02:24adminsetmessages: + msg15149
2025-10-10 00:00:00admincreate