1. Problem It Solves
The same logical coordinates can map to memory in different orders, and element access may require a custom policy. mdspan separates extents, layout mapping, and accessor for zero-overhead customization. The goal is to make the relevant rule visible in code instead of relying on an assumption about what “C++23 support” means.
2. Prerequisites
Day 50: mdspan ownership and extents.
Day 4: policy-based generic types.
3. Core Idea
Extents define the grid, a layout mapping converts coordinates to an offset, and an accessor turns a handle plus offset into the exposed reference or value. Read the syntax from left to right, identify the value, object, or range being transformed, and then check its resulting type, lifetime, or ownership. Standardization and implementation are separate: a C++23 mode may still lack one library component, so a feature-test macro is part of responsible portable use.
4. Minimal Syntax
std::mdspan<T, Extents, std::layout_left, Accessor> view(data);5. How It Works
The sample builds the smallest expression or object needed for
mdspanLayouts, Mappings, and Accessors.It compares layout offsets and uses a tiny read accessor when mdspan is implemented. The compiler and library apply the relevant rule before the program observes the result.
The program prints or checks different offsets for the same coordinate and an accessor-adjusted value, making the important behavior easy to verify.
6. Common Mistakes
Using a layout inconsistent with external storage silently reads the wrong elements; a custom accessor that returns a dangling proxy or violates its offset contract breaks the view.
Enabling C++23 mode without checking the relevant feature macro may select code that the installed compiler or standard library does not implement yet.
7. When to Use It
Use it when the task involves interop with row-major, column-major, strided, device, or specially accessed memory.
Avoid it when the task involves inventing a custom policy when
layout_rightanddefault_accessoralready match storage.
8. Simple Example
A column-major scientific array uses layout_left, while a checking accessor exposes values through a controlled read policy. The downloadable program keeps the data fixed so the output can be compared without entering input.
Complete sample code
Source file
cpp23/51_mdspan_layouts_mappings_accessors/main.cpp
#include <array>
#include <cstddef>
#include <iostream>
#include <version>
#if __has_include(<mdspan>)
#include <mdspan>
#endif
#if defined(__cpp_lib_mdspan)
struct DoubleAccessor {
using offset_policy = DoubleAccessor;
using element_type = const int;
using reference = int;
using data_handle_type = const int*;
constexpr reference access(data_handle_type data,
std::size_t index) const noexcept {
return data[index] * 2;
}
constexpr data_handle_type offset(data_handle_type data,
std::size_t index) const noexcept {
return data + index;
}
};
#endif
int main() {
#if defined(__cpp_lib_mdspan)
using Shape = std::extents<std::size_t, 2, 3>;
using Left = std::layout_left::mapping<Shape>;
using Right = std::layout_right::mapping<Shape>;
using View = std::mdspan<const int, Shape,
std::layout_left, DoubleAccessor>;
std::array data{1, 2, 3, 4, 5, 6};
View view(data.data(), Left{}, DoubleAccessor{});
std::cout << "left offset=" << Left{}(1, 0)
<< " right offset=" << Right{}(1, 0)
<< " value=" << view[1, 2] << '\n';
#else
std::cout << "mdspan policies unavailable\n";
#endif
}
9. Key Takeaways
Separate the language rule from compiler and library availability.
Keep lifetime, ownership, and deduced types visible when they affect correctness.
Prefer the smallest syntax that communicates the intent.
Guard facilities that are not yet uniformly implemented.
10. Self-Check Questions
Easy — What is the smallest syntax in Section 4, and what main job does it perform?
Medium — Read the sample program: which value, type, or branch is observed, and why?
Hard — For a
2 × 3matrix, how dolayout_leftandlayout_rightmap coordinate(1, 0), and which storage order does each imply?