C++ Logo

std-discussion

Advanced search

[mdspan.sub.helpers] `canonical-slice` seems to cross `.offset` and `.extent` in the `extent_slice` branch

From: Abhinav Agarwal <abhinavagarwal1996_at_[hidden]>
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

Received on 2026-06-05 15:06:23