Title
Bullet (4.3) preconditions are too strict to implement `submdspan`
Status
new
Section
[mdspan.layout.stride.cons]
Submitter
Mark Hoemmen

Created on 2026-07-15.00:00:00 last changed 3 days ago

Messages

Date: 2026-07-20.14:21:48

Proposed resolution:

This wording is relative to N5054.

[Drafting note: The proposed wording currently misses to account for extents of zero or 1]

  1. Modify [mdspan.layout.stride.cons] as indicated:

    template<class OtherIndexType>
      constexpr mapping(const extents_type& e, span<OtherIndexType, rank_> s) noexcept;
    template<class OtherIndexType>
      constexpr mapping(const extents_type& e, const array<OtherIndexType, rank_>& s) noexcept;
    

    -3- Constraints: […]

    -4- Preconditions:

    1. (4.1) — The result of converting s[i] to `index_type` is greater than `0` for all i in the range [0, rank_).

    2. (4.2) — REQUIRED-SPAN-SIZE(e, s) is representable as a value of type `index_type` ([basic.fundamental]).

    3. (4.3) — If rank_ is greater than `0`, then there exists a permutation P of the integers in the range [0, rank_), such that s[pi] >= s[pi-1] * e.extent(pi-1) s[pi] >= 1 + (e.extent(pi-1) - 1) * s[pi-1] is `true` for all i in the range [1, rank_), where pi is the ith element of P.

      [Note 1: For `layout_stride`, this condition is necessary and sufficient for `is_unique()` to be `true`. — end note]

    -5- Effects: Direct-non-list-initializes extents_ with `e`, and for all d in the range [0, rank_), direct-non-list-initializes strides_[d] with as_const(s[d]).

Date: 2026-07-15.00:00:00

For `layout_stride::mapping`'s constructor that takes an extents object and an array (or span) of strides, the preconditions on the strides are too strict. This makes it impossible to implement `submdspan`.

For an example see here. Let `x` be an `mdspan` such that `x.mapping()` is `layout_right::mapping` with extents (2, 5).

// slice denotes indices {0,2,4} out of original {0,1,2,3,4}.
std::extent_slice slice{.offset=0, .extent=3, .stride=2};
auto x_sub = std::submdspan(x, std::full_extent, slice);
assert(x_sub.extent(0) == 2);
assert(x_sub.extent(1) == 3);
assert(x_sub.stride(0) == 5);
assert(x_sub.stride(1) == 2);

x_sub's `layout_type` is `layout_stride`. However, the only way to construct `layout_stride::mapping` with these extents and strides would be to call the constructor that takes an extents object and an array (or span) of strides, and the above extents and strides would violate the preconditions.

// Extents and strides violate precondition of layout_stride::mapping
// constructor ([mdspan.layout.stride.cons] 4.3).
assert(! (x_sub.stride(1) >= x_sub.stride(0) * x_sub.extent(0)));
assert(! (x_sub.stride(0) >= x_sub.stride(1) * x_sub.extent(1)));

The fix is to relax the preconditions so that they test only the possibility of overlap.

assert(! (x_sub.stride(1) >= 1 + (x_sub.extent(0) - 1) * x_sub.stride(0)));
assert(   x_sub.stride(0) >= 1 + (x_sub.extent(1) - 1) * x_sub.stride(1));
History
Date User Action Args
2026-07-18 14:22:55adminsetmessages: + msg16526
2026-07-15 00:00:00admincreate