C++ Logo

std-proposals

Advanced search

Re: [std-proposals] `random_access_iterator_accessor` for `std::mdspan`?

From: Hewill Kang <hewillk_at_[hidden]>
Date: Fri, 3 Apr 2026 02:26:13 +0800
>
> I suspect what you want is first to get the value_type with
> iter_value_t, and then deduce const-ness from
> indirectly_writable<Iterator, value_type>.


It's unclear whether this can also be achieved by borrowing the standard
exposition-only concept of `constant-iterator` from [const.iterators.alias]
<https://eel.is/c++draft/const.iterators.alias>.

Mark Hoemmen <mark.hoemmen_at_[hidden]> 於 2026年4月3日週五 上午1:24寫道:

> On Wed, Apr 1, 2026 at 7:48 PM Hewill Kang <hewillk_at_[hidden]> wrote:
> >
> > Hi Mark,
> >
> > Thank you for your continued detailed clarification and explanation for
> mdspan; I have benefited greatly from it.
>
> Thank you for taking the time to revisit this! It's much improved.
>
> Regarding "Deduction of element_type and reference," the intent is
> that `element_type` is a cv-qualified `value_type`. This is why
> mdspan defines `value_type` as `remove_cv_t<element_type>`. Note that
> [mdspan.mdspan.overview] 2.3 Mandates that the first template argument
> of mdspan matches the accessor's element_type.
>
> This means that your current design won't work correctly with proxy
> reference types. Users would have to specify the proxy reference type
> (e.g., std::vector<bool>::reference) as the first template argument of
> mdspan, instead of the cv-qualified value type (e.g., bool).
>
> mdspan was designed to work with proxy reference types. Users of
> mdspan don't need to spell out the reference type, because that would
> unnecessarily couple mdspan to the accessor type. The accessor type
> already has the `reference` type alias; users shouldn't have to spell
> it out again.
>
> I suspect what you want is first to get the value_type with
> iter_value_t, and then deduce const-ness from
> indirectly_writable<Iterator, value_type>.
>
> >> Have you considered adding converting constructors so that users can
> >> go from an iterator-to-nonconst to an iterator-to-const?
> >
> > The proposed wording has the following converting constructors:
> >
> > template<convertible_to<I> I2>
> > constexpr iterator_accessor(iterator_accessor<I2>) noexcept {}
> >
> > I think it's enough to cover it?
>
> The analog of this is enough for `default_accessor`, but that only has
> to deal with pointers. If I is constructible from I2, but I2 is not
> convertible to I, then the same should be true of the accessor. As a
> result, mdspan conversion would work in the same way as accessor
> conversion. This is the design intent of mdspan.
>
> Thanks!
> mfh
>
> >
> >> My only concern is that the
> >> non-wording sections of the paper say some things about mdspan's
> >> design that I don't think are quite accurate.
> >
> >
> > Thank you for pointing it out.
> > In fact, a large part of the discussion section was written with AI
> assistance. :)
> > I neglected to proofread it, resulting in overly aggressive words, given
> that it might not fully understand mdspan. I have revised the discussion.
> >
> > Additionally, note that I used __cpp_lib_iterator_accessor because the
> standard already has a similar __cpp_lib_aligned_accessor.
> >
> > Here is the revised one: https://isocpp.org/files/papers/P4173R0.html
> >
> > Hewill
> >
> > Mark Hoemmen <mark.hoemmen_at_[hidden]> 於 2026年4月2日週四 上午1:51寫道:
> >>
> >> Hewill Kang wrote:
> >> > Hi, I wrote a paper on this:
> https://isocpp.org/files/papers/P4173R0.html
> >>
> >> Hi and thanks for your interest in mdspan!
> >>
> >> I do think a "random access iterator accessor" would be useful. I've
> >> actually implemented this for some of my colleagues, who asked for a
> >> proposal like this.
> >>
> >> Have you considered adding converting constructors so that users can
> >> go from an iterator-to-nonconst to an iterator-to-const?
> >>
> >> I generally approve of this proposal. My only concern is that the
> >> non-wording sections of the paper say some things about mdspan's
> >> design that I don't think are quite accurate.
> >>
> >> > Standard mdspan accessors are primarily limited to raw pointers,
> hindering direct integration with non-contiguous C++ Ranges and proxy-based
> containers.
> >>
> >> It's true that default_accessor and aligned_accessor work on pointers.
> >> However, mdspan's design actively encourages users to write custom
> >> accessors. Just like the Standard can't foresee all possible
> >> containers, the Standard can't foresee all possible custom accessors
> >> that users might like to write for their custom hardware. That's why
> >> it's a customization point. There are a few other places in the paper
> >> that say things like this. Would you consider correcting them?
> >>
> >> > ... hindering direct integration with non-contiguous C++ Ranges
> >>
> >> mdspan integrates perfectly well with ranges.
> >>
> >> template<class ElementType, class Extents, class Layout, class Accessor>
> >> constexpr auto to_index_range(extents<IndexType, Exts...> e) {
> >> auto [...index_views] =
> >> [] <size_t... Inds> (const auto& exts, index_sequence<Inds>) {
> >> return tuple{views::indices(exts.extent(Inds))...};
> >> } (e, make_index_sequence<sizeof...(Exts)>());
> >> return views::cartesian_product(index_views...);
> >> }
> >>
> >> template<class ElementType, class Extents, class Layout, class Accessor>
> >> constexpr auto to_range(mdspan<ElementType, Extents, Layout, Accessor>
> x) {
> >> if constexpr (std::is_same_v<Layout, layout_right>) {
> >> return views::indices(x.required_span_size()) |
> >> views::transform(
> >> [acc = x.accessor(), handle = x.data_handle()] (size_t k) {
> >> return acc.access(handle, k);
> >> });
> >> } else {
> >> return to_index_range(x.extents()) | views::transform([=] (auto t) {
> >> auto [...indices] = t;
> >> return x[indices...];
> >> });
> >> }
> >> }
> >>
> >> There, now you have `to_range(x)`. I haven't proposed this for the
> >> Standard for two reasons.
> >>
> >> 1. What would it mean to `std::copy` from a 2 x 3 x 5 x 7 mdspan to a
> >> 6 x 15 x 7 mdspan?
> >>
> >> 2. Compilers are unlikely to be able to optimize a "multidimensional
> iterator."
> >>
> >> 3. It might be a surprising pessimization that `layout_left` mdspan
> >> would still be iterated in row-major order.
> >>
> >> It's important to understand WHY mdspan uses accessors instead of
> >> iterators. The design intent is that accessors are easy to write for
> >> hardware experts who are not C++ experts, because it's much more
> >> likely that users will want to write a custom accessor (to support the
> >> huge variety of custom memory access patterns and network hardware
> >> that exists in practice) than it is that they will want to write a
> >> custom layout mapping. Iterators are hard to write correctly -- hard
> >> enough that proposals like Zach Laine's P2727 exist to make this
> >> easier.
> >>
> >> All that being said, I don't object to the proposal! I just want to
> >> help clear up the design intent of mdspan.
> >>
> >> Thanks!
> >> mfh
>

Received on 2026-04-02 18:26:27