I'd like to understand how the std::layout_stride policy for the std::mdspan works. At this point, no compiler supports this new C++23 library type, although a reference implementation exists: https://github.com/kokkos/mdspan. However, I could not find a good explanation on this layout type either on the github wiki (A Gentle Introduction to mdspan) or the P0009r18 paper.
The following program, using std::layout_right (the default) for an mdspan prints
1 2 3
4 5 6
std::vector v {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30};
std::mdspan<int,
std::extents<size_t, 2, 3>,
std::layout_right> mv{v.data()};
for (std::size_t r = 0; r < mv.extent(0); r++)
{
for (std::size_t c = 0; c < mv.extent(1); c++)
{
std::cout << mv[r, c] << ' ';
}
std::cout << '\n';
}
If we change to std::layout_left, the output becomes:
1 3 5
2 4 6
std::mdspan<int,
std::extents<size_t, 2, 3>,
std::layout_left> mv{v.data()};
My understanding is that std::layout_stride can control the stride. For instance, jumping every 2 elements (from the underlying sequence) for rows and 3 elements for columns. However, I did not find any example on this matter. Does anyone have examples showing how this really works?
It can be experimented on godbolt here: https://godbolt.org/z/Mxa7cej1a.
UPDATE
Based on the answer from @KamilCuc, I deduce the following:
stdex::mdspan<int,
stdex::extents<size_t, stdex::dynamic_extent, stdex::dynamic_extent>,
stdex::layout_stride>
mv{ v.data(),
{ stdex::dextents<size_t,2>{2, 3},
std::array<std::size_t, 2>{3, 1}}};
result:
1 2 3
4 5 6
This is the equivalent of layout_right.
stride: std::array<std::size_t, 2>{1, 1}
1 2 3
2 3 4
stride: std::array<std::size_t, 2>{3, 2}
1 3 5
4 6 8
stride: std::array<std::size_t, 2>{9, 3}
1 4 7
10 13 16
Answer inspired by OP's update which in turn was inspired by @KamilCuc's comment:
Using CTAD* one can nicely create an
mdspanwithlayout_stridelike this:These particular
stridesjust result in the same mapping aslayout_right. I refer back to OP's update for further examples of different strides.CTAD will cause
mdspanto infer the data type fromv.data(), and both theextents(including index type) and the layout from the mapping passed as the second argument to the constructor. In this example CTAD is also used to deduce theextentstemplate argument oflayout_stride::mapping. One could go even further with CTAD like here:Note that one cannot use
dextentswith CTAD which makes sense as they are there as a shortcut when not using CTAD and writingdextentswith CTAD would actually be longer than writingextents. The resultingextentstype is the same.*Class Template Argument Deduction