mdspan/memacc.hpp

The following code example is taken from the book
C++23 - The Complete Guide by Nicolai M. Josuttis, Leanpub, 2026
The code is licensed under a Creative Commons Attribution 4.0 International License. Creative Commons License

// raw code

#include <vector>
#include <memory>
#include <concepts>
#include <mdspan>
#include <type_traits>

template<std::integral ElemT>
class MemoryAccessor
{
private:
  using DataT = std::vector<ElemT>;  // type of the underlying data source
  std::shared_ptr<DataT> spData{};   // shared pointer to the underlying vector
  std::size_t size = 0;              // current number of elements

public:
  // required accessor types:
  using element_type = ElemT;                   // type of an element
  using reference = ElemT&;                     // reference to an element
  using data_handle_type = DataT::iterator;     // handle to the data/elements
  using offset_policy = MemoryAccessor<ElemT>;  // type to deal with offsets

  // constructor
  // - allocate and initialize underlying data source with dummy values
  constexpr MemoryAccessor(std::size_t sz) noexcept
   : size{sz} {
    spData.reset(new DataT(size));  // MUST be parentheses, no braces
    // dummy initialization with 1 2 3 ... :
    for (auto i = 0uz; i < size; ++i) {
      (*spData)[i] = static_cast<ElemT>(i+1);  
    }
  }

  // initial handle to pass to the mdspan:
  data_handle_type dataHandle() const {
    return (*spData).begin();
  }

  // element access:
  constexpr reference access(data_handle_type p, std::size_t n) const noexcept {
    return *(p + n);   // yield a reference to the n-th element starting with p
  }

  // define the effect of offsets:
  constexpr typename offset_policy::data_handle_type
  offset(data_handle_type p, std::size_t n) const noexcept {
    return p + n;      // move the iterator forward by n elements
  }
};