This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of Ready status.
submdspanSection: 23.7.3.4.7.3 [mdspan.layout.stride.cons] Status: Ready Submitter: Mark Hoemmen Opened: 2026-07-15 Last modified: 2026-07-31
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 Ready 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));
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.3 [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]).
[2026-07-24; Tomasz provides updated wording.]
Patch implementing the proposed resolution can be found here.
The note is adjusted as below condition is sufficient, but not necessary to guarantee uniqueness,
consider strides (3, 5) and extents (5, 3). They do not meet the requirements
but produce unique mapping:
0 1 2 3 4
----------------------
0| 0 3 6 9 12
1| 5 8 11 14 17
2| 10 13 16 19 22
[2026-07-31 LWG telecon; Status changed: New → Ready.]
Proposed resolution:
This wording is relative to N5054 with modifications from LWG 4603(i).
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) —
extents_type::index-cast(s[i])is non-negative and representable as a value of typeindex_type(6.9.3 [basic.fundamental]) for alliin the range[0, rank_).(4.2) —
REQUIRED-SPAN-SIZE(e, s)is representable as a value of typeindex_type.(4.3) — If both
rank_and the size of the multidimensional index spaceextents()are greater than0, then there exists a permutationPof the integers in the range[0, rank_)and valuem, such thatwhere
(4.3.1) —
e.extent(i) == 1istruefor alliin the range[0, m),(4.3.2) —
e.extent(i) > 1istruefor alliin the range[m, rank_),(4.3.3) — if
m < rank_istrue, thens[pis0m] > 0trueand for alliin the range[m+1, rank_),s[pi]is greater than sum of>=s[pi-1j] * (e.extent(pij)-1)isfor alltruein the rangeij,[1, rank_)[m, i)pkis thekthelement ofP.[Note: For
layout_stride, this condition isnecessary andsufficient foris_unique()to betrue. — end note]-5- Effects: […]