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.
// 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
}
};