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.
submdspan_mapping of rank-one padded layouts ignores the stride of an extent_slice,
and the sliceable postcondition does not mention stridesSection: 23.7.3.7.7.6 [mdspan.sub.map.leftpad], 23.7.3.7.7.7 [mdspan.sub.map.rightpad], 23.7.3.7.7.1 [mdspan.sub.map.sliceable] Status: New Submitter: Andrii Chornyi Opened: 2026-10-17 Last modified: 2026-10-31
Priority: Not Prioritized
View all issues with New status.
Discussion:
23.7.3.7.7.6 [mdspan.sub.map.leftpad] (and its mirror 23.7.3.7.7.7 [mdspan.sub.map.rightpad])
specify the result of layout_left_padded::mapping<Extents>::submdspan-mapping-impl(slices...).
Bullet (1.2) of the Returns element reads:
otherwise,
submdspan_mapping_result{layout_left::mapping(sub_ext), offset}, ifrank_== 1istrueorSubExtents::rank() == 0istrue;
The first part of the condition applies to every slice of a rank-one mapping, including a strided one.
For rank_ == 1 and the slice extent_slice{0, cw<4>, cw<2>} the result has
SubExtents::rank() == 1 with extent 2, and layout_left::mapping(sub_ext) has stride 1. The returned
mapping therefore addresses the first two elements 0, 1 (plus offset) instead of elements 0, 2.
s that
is an extent_slice with s.extent > 1, the stride of the corresponding sub-dimension is stride(k) * s.stride
(the list that defines sub_strides), so the strided slice yields a layout_stride mapping with stride 2.
The layout_left, layout_right and layout_stride specializations (23.7.3.7.7.3 [mdspan.sub.map.left],
23.7.3.7.7.4 [mdspan.sub.map.right], 23.7.3.7.7.5 [mdspan.sub.map.stride]) are unaffected; only the padded
specializations contain the rank_ == 1 shortcut. Unit-stride slices are unaffected.
The generic requirement that is meant to catch this does not do so: 23.7.3.7.7.1 [mdspan.sub.map.sliceable]
Returns (5.2) requires
smr.mapping(i...) + smr.offset == m(j), wherej...[ρ]is equal to the sum of the lower bound of thesubmdspanslice range ... and zero if the type ofvalid_slices...[ρ]is a collapsing slice type,i...[MAP_RANK(valid_slices,ρ)]otherwise.
The index i is added to the lower bound without being multiplied by the slice stride. Read literally,
the (stride-1) layout_left::mapping above satisfies this postcondition, while a correct layout_stride
result for the same slice (the result that 23.7.3.7.7.2 [mdspan.sub.map.common] itself prescribes for the
default mappings) does not. The two defects hide each other: the postcondition can neither detect the wrong
rank-one result nor accept the right one.
layout_left_padded<dynamic_extent>::mapping<extents<int, 8>> with
submdspan_mapping(m, extent_slice{0, cw<4>, cw<2>}): smr.mapping(1) + smr.offset is 1,
m(2) is the element the slice selects as its second element.
Proposed resolution:
This wording is relative to N5054.
Modify 23.7.3.7.7.6 [mdspan.sub.map.leftpad] as indicated:
[Drafting note: The case
rank_ == 1with a unit-stride slice andSubExtents::rank() == 1is covered by the third bullet (SubExtents::rank() == 1andSliceSpecifiers...[0]is a unit-stride slice type, same result); a strided slice falls to the last bullet and yields thelayout_stridemapping.]
template<class Extents> template<class... SliceSpecifiers> constexpr auto layout_left_padded::mapping<Extents>::submdspan-mapping-impl( SliceSpecifiers... slices) const -> see below;-1- Returns:
(1.1) —
submdspan_mapping_result{*this, 0}, ifExtents::rank() == 0istrue;(1.2) — otherwise,
submdspan_mapping_result{layout_left::mapping(sub_ext), offset}, ifrank_ == 1istrueorSubExtents::rank() == 0istrue;
Modify 23.7.3.7.7.7 [mdspan.sub.map.rightpad] as indicated:
template<class Extents> template<class... SliceSpecifiers> constexpr auto layout_right_padded::mapping<Extents>::submdspan-mapping-impl( SliceSpecifiers... slices) const -> see below;-1- Returns:
(1.1) —
submdspan_mapping_result{*this, 0}, ifrank_ == 0istrue;(1.2) — otherwise,
submdspan_mapping_result{layout_right::mapping(sub_ext), offset}, ifrank_ == 1istrueorSubExtents::rank() == 0istrue;
Modify 23.7.3.7.7.1 [mdspan.sub.map.sliceable] as indicated:
-3- A type
[…] -4- Result: A typeMmeets the sliceable layout mapping requirements ifSMRthat is a specialization of typesubmdspan_mapping_result<SM>for some typeSMsuch that […] -5- Returns: An objectsmrof typeSMRsuch that
(5.1) —
smr.mapping.extents() == subextents(m.extents(), valid_slices...)istrue; and(5.2) — for each integer pack
iwhich is a multidimensional index insmr.mapping.extents(),smr.mapping(i...) + smr.offset == m(j)istrue, wherejis an integer pack such that
(5.2.1) —
sizeof...(j)is equal toM_rank; and(5.2.2) — for each rank index ρ of
m.extents(),j...[ρ]is equal to the sum of
(5.2.2.1) — the lower bound of the
submdspanslice range ofvalid_slices...[ρ]for extent ρ ofm.extents(), and(5.2.2.2) — zero if the type of
valid_slices...[ρ]is a collapsing slice type,otherwise, the product ofi...[MAP_RANK(valid_slices,ρ)]i...[MAP_RANK(valid_slices,ρ)]ands.strideif the type ofvalid_slices...[ρ]is a specialization ofextent_sliceands.extent > 1istrue, wheresisvalid_slices...[ρ], andi...[MAP_RANK(valid_slices,ρ)]otherwise.