Date: Fri, 5 Jun 2026 08:05:51 -0700
Hello,
While reading the post-P3982R2 `[mdspan.sub.*]` wording in N5050, I
noticed what looks like a
swapped initializer in the `canonical-slice` helper on the core
`submdspan` path.
In the *Effects: Equivalent to:* of `canonical-slice`
([mdspan.sub.helpers]), the branch for a
runtime `extent_slice` reads (https://eel.is/c++draft/mdspan.sub.helpers):
```
} else if constexpr (is-extent-slice<S>) {
return extent_slice{
.offset = canonical-index<IndexType>(std::move(s.extent)),
.extent = canonical-index<IndexType>(std::move(s.offset)),
.stride = canonical-index<IndexType>(std::move(s.stride))
};
}
```
`.offset` is initialized from `s.extent` and `.extent` from
`s.offset`. Reading it literally,
`extent_slice{.offset = 5, .extent = 4, .stride = 2}` canonicalizes to
`{.offset = 4, .extent = 5}`,
so the `submdspan` slice range becomes `[4, 13)` instead of the
intended `{5, 7, 9, 11}`. As far as
I can tell, nothing downstream un-swaps: the slice range,
`subextents`, and the valid-slice checks
all consume the canonicalized slice as-is.
This looks like a transcription slip rather than a design point: the
sibling helper
`canonical-range-slice` uses the un-crossed mapping, and the
pre-P3982R2 body also mapped
offset ->offset and extent -> extent.
Am I misreading this, or should those two initializers simply be swapped back?
Abhinav Agarwal
While reading the post-P3982R2 `[mdspan.sub.*]` wording in N5050, I
noticed what looks like a
swapped initializer in the `canonical-slice` helper on the core
`submdspan` path.
In the *Effects: Equivalent to:* of `canonical-slice`
([mdspan.sub.helpers]), the branch for a
runtime `extent_slice` reads (https://eel.is/c++draft/mdspan.sub.helpers):
```
} else if constexpr (is-extent-slice<S>) {
return extent_slice{
.offset = canonical-index<IndexType>(std::move(s.extent)),
.extent = canonical-index<IndexType>(std::move(s.offset)),
.stride = canonical-index<IndexType>(std::move(s.stride))
};
}
```
`.offset` is initialized from `s.extent` and `.extent` from
`s.offset`. Reading it literally,
`extent_slice{.offset = 5, .extent = 4, .stride = 2}` canonicalizes to
`{.offset = 4, .extent = 5}`,
so the `submdspan` slice range becomes `[4, 13)` instead of the
intended `{5, 7, 9, 11}`. As far as
I can tell, nothing downstream un-swaps: the slice range,
`subextents`, and the valid-slice checks
all consume the canonicalized slice as-is.
This looks like a transcription slip rather than a design point: the
sibling helper
`canonical-range-slice` uses the un-crossed mapping, and the
pre-P3982R2 body also mapped
offset ->offset and extent -> extent.
Am I misreading this, or should those two initializers simply be swapped back?
Abhinav Agarwal
Received on 2026-06-05 15:06:23
