C++ Logo

std-proposals

Advanced search

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

From: Hewill Kang <hewillk_at_[hidden]>
Date: Mon, 30 Mar 2026 20:33:20 +0800
Hi all,

Currently, although `mdspan` is designed as a general-purpose multiview, it
mostly accepts a pointer and accesses different elements through a pointer
algorithm.
However, I am not satisfied with these *pointer*-based mandates because I
do not think they are much different from a general `contiguous_iterator`,
which can be a common iterator such as `vector::iterator`.
If we look at the `default_accessor`, we can see the clue:

```cpp
template<class ElementType>
  struct default_accessor {
    using offset_policy = default_accessor;
    using element_type = ElementType;
    using reference = ElementType&;
    using data_handle_type = ElementType*;

    constexpr default_accessor() noexcept = default;
    constexpr reference access(data_handle_type p, size_t i) const noexcept
      { return p[i]; }
    constexpr data_handle_type offset(data_handle_type p, size_t i) const
noexcept
      { return p + i; }
  };
```
Then, upon closer inspection, we discovered that this is *exactly* the
operation supported by C++20 `random_access_iterator`, i.e.,
`operator[]` and `operator+`.
Given this, I think we can introduce a new accessor class that wraps the
`random_access_iterator`, for example:

```cpp
template<random_access_iterator I>
  struct *iter_accessor* {
    using offset_policy = iter_accessor;
    using reference = iter_reference_t<I>;
    using element_type = remove_reference_t<reference>;
    using data_handle_type = I;

    iter_accessor() noexcept = default;
    constexpr reference
      access(data_handle_type p, std::iter_difference_t<I> i) const
        { return p[i]; }
    constexpr data_handle_type
      offset(data_handle_type p, std::iter_difference_t<I> i) const
        { return p + i; }
  };
```

This fully inherits the natural characteristics of a
`random_access_iterator`, which allows us to very easily make `mdspan`s
with a wide variety of different `random_access_range`s, such as:

```
  using Layout = std::layout_right::mapping<std::extents<int, 3, 3>>;

  auto r = std::views::iota(0, 9);
  auto ms1 = std::mdspan(r.begin(), Layout{}, *iter_accessor*
<decltype(r.begin())>{});
  /* 0 1 2
     3 4 5
     6 7 8 */

  auto v = std::vector<bool>{true, false, true, false, true, false, true,
false, true};
  auto ms2 = std::mdspan(v.begin(), Layout{}, *iter_accessor*
<decltype(v.begin())>{});
  /* true false true
     false true false
     true false true */

  std::vector<int> v1{1, 2, 3}, v2{4, 5}, v3{};
  std::array a{6, 7, 8};
  auto s = std::views::single(9);
  auto r3 = std::views::concat(v1, v2, v3, a, s);
  auto ms3 = std::mdspan(r3.begin(), Layout{}, *iter_accessor*
<decltype(r3.begin())>{});
  /* 1 2 3
      4 5 6
      7 8 9 */
```
Demo: https://godbolt.org/z/xb5vrejba

I think this is a very useful utility.
Based on C++26, we have a large majority of range adaptors in `<ranges>`
that can support `random_access_range`.
Introducing this `accessor` makes them better integrated with `mdspan`,
which also opens the door for third-party custom range types.

What do you think? Appreciate any feedback.

Hewill

Received on 2026-03-30 12:33:36