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.
layout_left_padded::mapping and layout_right_padded::mapping are
missing a representability precondition for the padded strideSection: 23.7.3.4.8.3 [mdspan.layout.leftpad.cons], 23.7.3.4.9.3 [mdspan.layout.rightpad.cons] Status: New Submitter: Xi Chen Opened: 2026-03-18 Last modified: 2026-03-21
Priority: Not Prioritized
View all issues with New status.
Discussion:
It appears that these constructors are missing a precondition requiring the incoming padded stride to
be representable as a value of the destination index_type.
other.required_span_size() is representable as a value of type
index_type, but that is not sufficient when the source mapping is empty. In that case,
other.required_span_size() can be 0 even though the source padded stride is too large for the
destination index_type. The padded stride is then silently truncated, and that truncation is observable
through stride().
Example:
#include <mdspan>
#include <cstdint>
#include <cassert>
void test() {
using Src = std::layout_left_padded<std::dynamic_extent>::mapping<std::extents<uint32_t, 1, 0>>;
using Dst = std::layout_left_padded<std::dynamic_extent>::mapping<std::extents<uint8_t, 1, 0>>;
// src.stride(1) == 256.
Src src(std::extents<uint32_t, 1, 0>(), 256);
// other.required_span_size() is 0, so the existing preconditions are met.
// The stored padded stride is then converted to uint8_t and truncated to 0.
Dst dst(src);
assert(dst.stride(1) == 0);
}
Proposed resolution:
This wording is relative to N5032.
Modify 23.7.3.4.8.3 [mdspan.layout.leftpad.cons] as indicated:
template<class OtherExtents> constexpr explicit(see below) mapping(const layout_stride::mapping<OtherExtents>& other);-10- Constraints: […]
-11- Preconditions:
(11.1) — […]
(11.2) — […]
(11.3) — […]
(11.4) —
other.required_span_size()is representable as a value of typeindex_type.(11.5) — If
rank_is greater than1andstatic-padding-strideequalsdynamic_extent,other.stride(1)is representable as a value of typeindex_type.-12- Effects: […]
-13- Remarks: […]template<class LayoutLeftPaddedMapping> constexpr explicit(see below) mapping(const LayoutLeftPaddedMapping& other);-14- Constraints: […]
-15- Mandates: […] -16- Preconditions:
(16.1) — […]
(16.2) —
other.required_span_size()is representable as a value of typeindex_type.(16.3) — If
rank_is greater than1andstatic-padding-strideequalsdynamic_extent,other.stride(1)is representable as a value of typeindex_type.-17- Effects: […]
-18- Remarks: […]
Modify 23.7.3.4.9.3 [mdspan.layout.rightpad.cons] as indicated:
template<class OtherExtents> constexpr explicit(see below) mapping(const layout_stride::mapping<OtherExtents>& other);-10- Constraints: […]
-11- Preconditions:
(11.1) — […]
(11.2) — […]
(11.3) — […]
(11.4) —
other.required_span_size()is representable as a value of typeindex_type.(11.5) — If
rank_is greater than1andstatic-padding-strideequalsdynamic_extent,other.stride(rank_ - 2)is representable as a value of typeindex_type.-12- Effects: […]
-13- Remarks: […]template<class LayoutRightPaddedMapping> constexpr explicit(see below) mapping(const LayoutRightPaddedMapping& other);-14- Constraints: […]
-15- Mandates: […] -16- Preconditions:
(16.1) — […]
(16.2) —
other.required_span_size()is representable as a value of typeindex_type.(16.3) — If
rank_is greater than1andstatic-padding-strideequalsdynamic_extent,other.stride(rank_ - 2)is representable as a value of typeindex_type.-17- Effects: […]
-18- Remarks: […]