This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.
submdspanSection: 23.7.3.4.7.3 [mdspan.layout.stride.cons] Status: New Submitter: Mark Hoemmen Opened: 2026-07-15 Last modified: 2026-07-20
Priority: Not Prioritized
View other active issues in [mdspan.layout.stride.cons].
View all other issues in [mdspan.layout.stride.cons].
View all issues with New status.
Discussion:
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.
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 (23.7.3.4.7.3 [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));
Proposed resolution:
This wording is relative to N5054.
[Drafting note: The proposed wording currently misses to account for extents of zero or 1]
Modify 23.7.3.4.7.3 [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:
(4.1) — The result of converting
s[i]toindex_typeis greater than0for alliin the range[0, rank_).(4.2) —
REQUIRED-SPAN-SIZE(e, s)is representable as a value of typeindex_type(6.9.2 [basic.fundamental]).(4.3) — If
[Note 1: Forrank_is greater than0, then there exists a permutationPof the integers in the range[0, rank_), such thats[pi] >= s[pi-1] * e.extent(pi-1)s[pi] >= 1 + (e.extent(pi-1) - 1) * s[pi-1]istruefor alliin the range[1, rank_), wherepiis theith element ofP.layout_stride, this condition is necessary and sufficient foris_unique()to betrue. — end note]-5- Effects: Direct-non-list-initializes
extents_withe, and for alldin the range[0, rank_), direct-non-list-initializesstrides_[d]withas_const(s[d]).