Date: Thu, 2 Apr 2026 11:24:01 -0600
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
>
> 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 17:24:23
