{"id":8208,"date":"2023-09-11T18:26:22","date_gmt":"2023-09-11T18:26:22","guid":{"rendered":"https:\/\/www.modernescpp.com\/?p=8208"},"modified":"2023-09-13T18:41:12","modified_gmt":"2023-09-13T18:41:12","slug":"c23-a-multidimensional-view","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c23-a-multidimensional-view\/","title":{"rendered":"C++23: A Multidimensional View"},"content":{"rendered":"\n<p>A <code>std::mdspan<\/code> is a non-owning multidimensional view of a contiguous sequence of objects. The contiguous sequence of objects can be a plain C-array, a pointer with a size, a <code>std::array<\/code>, a <code>std::vector<\/code>, or a <code>std::string<\/code>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1030\" height=\"579\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/Cpp23-2-1030x579.png\" alt=\"\" class=\"wp-image-8210\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/Cpp23-2-1030x579.png 1030w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/Cpp23-2-300x169.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/Cpp23-2-768x432.png 768w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/Cpp23-2-705x397.png 705w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/Cpp23-2.png 1280w\" sizes=\"auto, (max-width: 1030px) 100vw, 1030px\" \/><\/figure>\n\n\n\n<p>Often, this multidimensional view is called a multidimensional array.<\/p>\n\n\n\n<p>The number of dimensions and the size of each dimension determine the shape of the multidimensional array. The number of dimensions is called rank, and the size of each dimension extension. The size of the <code>std::mdspan<\/code> is the product of all dimensions that are not 0. You can access the elements of a <code>std::mdspan<\/code> using the multidimensional index operator <code>[]<\/code>.<\/p>\n\n\n\n<p>Each dimension of a <code>std::mdspan<\/code> can have a <em>static <\/em>or <em>dynamic extent<\/em>. <em>static extent<\/em> means that its length is specified at compile time; <em>dynamic extent<\/em> means that its length is specified at run time.<\/p>\n\n\n\n<p>Here is its definition:<\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;gray;border-width:.1em .1em .1em .8em\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #006699; font-weight: bold\">template<\/span><span style=\"color: #555555\">&lt;<\/span>\n    <span style=\"color: #006699; font-weight: bold\">class<\/span> <span style=\"color: #00AA88; font-weight: bold\">T<\/span>,\n    <span style=\"color: #006699; font-weight: bold\">class<\/span> <span style=\"color: #00AA88; font-weight: bold\">Extents<\/span>,\n    <span style=\"color: #006699; font-weight: bold\">class<\/span> <span style=\"color: #00AA88; font-weight: bold\">LayoutPolicy<\/span> <span style=\"color: #555555\">=<\/span> std<span style=\"color: #555555\">::<\/span>layout_right,\n    <span style=\"color: #006699; font-weight: bold\">class<\/span> <span style=\"color: #00AA88; font-weight: bold\">AccessorPolicy<\/span> <span style=\"color: #555555\">=<\/span> std<span style=\"color: #555555\">::<\/span>default_accessor<span style=\"color: #555555\">&lt;<\/span>T<span style=\"color: #555555\">&gt;<\/span>\n<span style=\"color: #555555\">&gt;<\/span> <span style=\"color: #006699; font-weight: bold\">class<\/span> <span style=\"color: #00AA88; font-weight: bold\">mdspan<\/span>;\n<\/pre><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li> <code>T<\/code>: the contiguous sequence of objects<\/li>\n\n\n\n<li><code>Extents<\/code>: specifies the number of dimensions as their size; each dimension can have a <em>static extent<\/em> or a <em>dynamic extent<\/em><\/li>\n\n\n\n<li><code>LayoutPolicy<\/code>: specifies the layout policy to access the underlying memory<\/li>\n\n\n\n<li><code>AccessorPolicy<\/code>: specifies how the underlying elements are referenced<\/li>\n<\/ul>\n\n\n\n<p>Thanks to class template argument deduction (CTAG) in C++17, the compiler can often automatically deduce the template arguments from the types of initializers:<\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;gray;border-width:.1em .1em .1em .8em\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #0099FF; font-style: italic\">\/\/ mdspan.cpp<\/span>\n\n<span style=\"color: #009999\">#include &lt;mdspan&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;iostream&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;vector&gt;<\/span>\n\n<span style=\"color: #007788; font-weight: bold\">int<\/span> <span style=\"color: #CC00FF\">main<\/span>() {\n    \n    std<span style=\"color: #555555\">::<\/span>vector myVec{<span style=\"color: #FF6600\">1<\/span>, <span style=\"color: #FF6600\">2<\/span>, <span style=\"color: #FF6600\">3<\/span>, <span style=\"color: #FF6600\">4<\/span>, <span style=\"color: #FF6600\">5<\/span>, <span style=\"color: #FF6600\">6<\/span>, <span style=\"color: #FF6600\">7<\/span>, <span style=\"color: #FF6600\">8<\/span>};          <span style=\"color: #0099FF; font-style: italic\">\/\/ (1)<\/span>\n\n    std<span style=\"color: #555555\">::<\/span>mdspan m{myVec.data(), <span style=\"color: #FF6600\">2<\/span>, <span style=\"color: #FF6600\">4<\/span>};                  <span style=\"color: #0099FF; font-style: italic\">\/\/ (2)<\/span>\n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;m.rank(): &quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> m.rank() <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;      <span style=\"color: #0099FF; font-style: italic\">\/\/ (4)<\/span>\n\n    <span style=\"color: #006699; font-weight: bold\">for<\/span> (std<span style=\"color: #555555\">::<\/span><span style=\"color: #007788; font-weight: bold\">size_t<\/span> i <span style=\"color: #555555\">=<\/span> <span style=\"color: #FF6600\">0<\/span>; i <span style=\"color: #555555\">&lt;<\/span> m.extent(<span style=\"color: #FF6600\">0<\/span>); <span style=\"color: #555555\">++<\/span>i) {     <span style=\"color: #0099FF; font-style: italic\">\/\/ (6)<\/span>\n        <span style=\"color: #006699; font-weight: bold\">for<\/span> (std<span style=\"color: #555555\">::<\/span><span style=\"color: #007788; font-weight: bold\">size_t<\/span> j <span style=\"color: #555555\">=<\/span> <span style=\"color: #FF6600\">0<\/span>; j <span style=\"color: #555555\">&lt;<\/span> m.extent(<span style=\"color: #FF6600\">1<\/span>); <span style=\"color: #555555\">++<\/span>j) { <span style=\"color: #0099FF; font-style: italic\">\/\/ (7)<\/span>\n            std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> m[i, j] <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39; &#39;<\/span>;                <span style=\"color: #0099FF; font-style: italic\">\/\/ (8)<\/span>\n        }\n        std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n    }\n\n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n\n    std<span style=\"color: #555555\">::<\/span>mdspan m2{myVec.data(), <span style=\"color: #FF6600\">4<\/span>, <span style=\"color: #FF6600\">2<\/span>};                 <span style=\"color: #0099FF; font-style: italic\">\/\/ (3)<\/span>\n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;m2.rank(): &quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> m2.rank() <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;    <span style=\"color: #0099FF; font-style: italic\">\/\/ (5)<\/span>\n\n    <span style=\"color: #006699; font-weight: bold\">for<\/span> (std<span style=\"color: #555555\">::<\/span><span style=\"color: #007788; font-weight: bold\">size_t<\/span> i <span style=\"color: #555555\">=<\/span> <span style=\"color: #FF6600\">0<\/span>; i <span style=\"color: #555555\">&lt;<\/span> m2.extent(<span style=\"color: #FF6600\">0<\/span>); <span style=\"color: #555555\">++<\/span>i) {\n        <span style=\"color: #006699; font-weight: bold\">for<\/span> (std<span style=\"color: #555555\">::<\/span><span style=\"color: #007788; font-weight: bold\">size_t<\/span> j <span style=\"color: #555555\">=<\/span> <span style=\"color: #FF6600\">0<\/span>; j <span style=\"color: #555555\">&lt;<\/span> m2.extent(<span style=\"color: #FF6600\">1<\/span>); <span style=\"color: #555555\">++<\/span>j) {\n        std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> m2[i, j] <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39; &#39;<\/span>;  \n    }\n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n  }\n\n}\n<\/pre><\/div>\n\n\n\n<p>I apply class template argument deduction three times in this example. Line (1) uses it for a<code> std::vector<\/code>, and lines (2) and (3) for a<code> std::mdspan<\/code>. The first 2-dimensional array <code>m <\/code>has a shape of (2, 4), the second one <code>m2 <\/code>a shape of (4, 2). Lines (4) and (5) display the ranks of both <code>std::mdspan<\/code>. Thanks to the extent of each dimension (lines 6 and 7) and the index operator in line (8), it is straightforward to iterate through multidimensional arrays.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"170\" height=\"231\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/mdspan.png\" alt=\"\" class=\"wp-image-8213\"\/><\/figure>\n\n\n\n<p>If your multidimensional array should have a <em>static extent<\/em>, you have to specify the template arguments.<\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;gray;border-width:.1em .1em .1em .8em\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #0099FF; font-style: italic\">\/\/ staticDynamicExtent.cpp<\/span>\n\n<span style=\"color: #009999\">#include &lt;mdspan&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;iostream&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;string&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;vector&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;tuple&gt;<\/span>\n\n<span style=\"color: #007788; font-weight: bold\">int<\/span> <span style=\"color: #CC00FF\">main<\/span>() {\n    \n    std<span style=\"color: #555555\">::<\/span>vector myVec{<span style=\"color: #FF6600\">1<\/span>, <span style=\"color: #FF6600\">2<\/span>, <span style=\"color: #FF6600\">3<\/span>, <span style=\"color: #FF6600\">4<\/span>, <span style=\"color: #FF6600\">5<\/span>, <span style=\"color: #FF6600\">6<\/span>, <span style=\"color: #FF6600\">7<\/span>, <span style=\"color: #FF6600\">8<\/span>};\n\n    std<span style=\"color: #555555\">::<\/span>mdspan<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">int<\/span>, std<span style=\"color: #555555\">::<\/span>extents<span style=\"color: #555555\">&lt;<\/span>std<span style=\"color: #555555\">::<\/span><span style=\"color: #007788; font-weight: bold\">size_t<\/span>, <span style=\"color: #FF6600\">2<\/span>, <span style=\"color: #FF6600\">4<\/span><span style=\"color: #555555\">&gt;&gt;<\/span> m{myVec.data()}; <span style=\"color: #0099FF; font-style: italic\">\/\/ (1)<\/span>\n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;m.rank(): &quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> m.rank() <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n\n    <span style=\"color: #006699; font-weight: bold\">for<\/span> (std<span style=\"color: #555555\">::<\/span><span style=\"color: #007788; font-weight: bold\">size_t<\/span> i <span style=\"color: #555555\">=<\/span> <span style=\"color: #FF6600\">0<\/span>; i <span style=\"color: #555555\">&lt;<\/span> m.extent(<span style=\"color: #FF6600\">0<\/span>); <span style=\"color: #555555\">++<\/span>i) {\n        <span style=\"color: #006699; font-weight: bold\">for<\/span> (std<span style=\"color: #555555\">::<\/span><span style=\"color: #007788; font-weight: bold\">size_t<\/span> j <span style=\"color: #555555\">=<\/span> <span style=\"color: #FF6600\">0<\/span>; j <span style=\"color: #555555\">&lt;<\/span> m.extent(<span style=\"color: #FF6600\">1<\/span>); <span style=\"color: #555555\">++<\/span>j) {\n            std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> m[i, j] <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39; &#39;<\/span>;  \n        }\n        std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n    }\n\n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n\n    std<span style=\"color: #555555\">::<\/span>mdspan<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">int<\/span>, std<span style=\"color: #555555\">::<\/span>extents<span style=\"color: #555555\">&lt;<\/span>std<span style=\"color: #555555\">::<\/span><span style=\"color: #007788; font-weight: bold\">size_t<\/span>, std<span style=\"color: #555555\">::<\/span>dynamic_extent, \n                std<span style=\"color: #555555\">::<\/span>dynamic_extent<span style=\"color: #555555\">&gt;&gt;<\/span> m2{myVec.data(), <span style=\"color: #FF6600\">4<\/span>, <span style=\"color: #FF6600\">2<\/span>};          <span style=\"color: #0099FF; font-style: italic\">\/\/ (2)<\/span>\n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;m2.rank(): &quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> m2.rank() <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n\n    <span style=\"color: #006699; font-weight: bold\">for<\/span> (std<span style=\"color: #555555\">::<\/span><span style=\"color: #007788; font-weight: bold\">size_t<\/span> i <span style=\"color: #555555\">=<\/span> <span style=\"color: #FF6600\">0<\/span>; i <span style=\"color: #555555\">&lt;<\/span> m2.extent(<span style=\"color: #FF6600\">0<\/span>); <span style=\"color: #555555\">++<\/span>i) {\n        <span style=\"color: #006699; font-weight: bold\">for<\/span> (std<span style=\"color: #555555\">::<\/span><span style=\"color: #007788; font-weight: bold\">size_t<\/span> j <span style=\"color: #555555\">=<\/span> <span style=\"color: #FF6600\">0<\/span>; j <span style=\"color: #555555\">&lt;<\/span> m2.extent(<span style=\"color: #FF6600\">1<\/span>); <span style=\"color: #555555\">++<\/span>j) {\n        std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> m2[i, j] <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39; &#39;<\/span>;  \n    }\n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n  }\n\n   std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n\n}\n<\/pre><\/div>\n\n\n\n<p>The program <code>staticDynamicExtent.cpp <\/code>is based on the previous program mdspan.cpp, and produces the same output. The difference is that the <code>std::mdspan m<\/code> (line 1) has a <em>static extent<\/em>. For completeness, <code>std::mdspan m2<\/code> (line 2) has a <em>dynamic extent<\/em>. Consequentially, the shape of <code>m <\/code>is specified with template arguments, but the shape <code>m2 <\/code>is with function arguments.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Layout Policy<\/h2>\n\n\n\n<p>A <code>std::mdspan<\/code> allows you to specify the layout policy to access the underlying memory. By default, <code>std::layout_right <\/code>(C, C++, or Python style) is used, but you can also specify <code>std::layout_left<\/code> (Fortran or MATLAB style). The following graphic exemplifies in which sequence the elements of the <code>std::mdspan<\/code> are accessed.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large is-resized\"><img decoding=\"async\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/LayoutMDspan-1030x299.png\" alt=\"\" class=\"wp-image-8218\" style=\"width:400px\" width=\"400\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/LayoutMDspan-1030x299.png 1030w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/LayoutMDspan-300x87.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/LayoutMDspan-768x223.png 768w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/LayoutMDspan-705x205.png 705w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/LayoutMDspan.png 1092w\" sizes=\"(max-width: 1030px) 100vw, 1030px\" \/><\/figure>\n\n\n\n<p>Traversing two <code>std::mdspan<\/code> with the layout policy <code>std::layout_right<\/code> and <code>std::layout_left<\/code> shows the difference.<\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;gray;border-width:.1em .1em .1em .8em\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #0099FF; font-style: italic\">\/\/ mdspanLayout.cpp<\/span>\n\n<span style=\"color: #009999\">#include &lt;mdspan&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;iostream&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;vector&gt;<\/span>\n\n<span style=\"color: #007788; font-weight: bold\">int<\/span> <span style=\"color: #CC00FF\">main<\/span>() {\n    \n    std<span style=\"color: #555555\">::<\/span>vector myVec{<span style=\"color: #FF6600\">1<\/span>, <span style=\"color: #FF6600\">2<\/span>, <span style=\"color: #FF6600\">3<\/span>, <span style=\"color: #FF6600\">4<\/span>, <span style=\"color: #FF6600\">5<\/span>, <span style=\"color: #FF6600\">6<\/span>, <span style=\"color: #FF6600\">7<\/span>, <span style=\"color: #FF6600\">8<\/span>};\n\n    std<span style=\"color: #555555\">::<\/span>mdspan<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">int<\/span>, std<span style=\"color: #555555\">::<\/span>extents<span style=\"color: #555555\">&lt;<\/span>std<span style=\"color: #555555\">::<\/span><span style=\"color: #007788; font-weight: bold\">size_t<\/span>,      <span style=\"color: #0099FF; font-style: italic\">\/\/ (1)<\/span>\n         std<span style=\"color: #555555\">::<\/span>dynamic_extent, std<span style=\"color: #555555\">::<\/span>dynamic_extent<span style=\"color: #555555\">&gt;<\/span>, \n         std<span style=\"color: #555555\">::<\/span>layout_right<span style=\"color: #555555\">&gt;<\/span> m{myVec.data(), <span style=\"color: #FF6600\">4<\/span>, <span style=\"color: #FF6600\">2<\/span>};\n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;m.rank(): &quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> m.rank() <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n\n    <span style=\"color: #006699; font-weight: bold\">for<\/span> (std<span style=\"color: #555555\">::<\/span><span style=\"color: #007788; font-weight: bold\">size_t<\/span> i <span style=\"color: #555555\">=<\/span> <span style=\"color: #FF6600\">0<\/span>; i <span style=\"color: #555555\">&lt;<\/span> m.extent(<span style=\"color: #FF6600\">0<\/span>); <span style=\"color: #555555\">++<\/span>i) {\n        <span style=\"color: #006699; font-weight: bold\">for<\/span> (std<span style=\"color: #555555\">::<\/span><span style=\"color: #007788; font-weight: bold\">size_t<\/span> j <span style=\"color: #555555\">=<\/span> <span style=\"color: #FF6600\">0<\/span>; j <span style=\"color: #555555\">&lt;<\/span> m.extent(<span style=\"color: #FF6600\">1<\/span>); <span style=\"color: #555555\">++<\/span>j) {\n            std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> m[i, j] <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39; &#39;<\/span>;  \n        }\n        std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n    }\n\n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n\n    std<span style=\"color: #555555\">::<\/span>mdspan<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">int<\/span>, std<span style=\"color: #555555\">::<\/span>extents<span style=\"color: #555555\">&lt;<\/span>std<span style=\"color: #555555\">::<\/span><span style=\"color: #007788; font-weight: bold\">size_t<\/span>,     <span style=\"color: #0099FF; font-style: italic\">\/\/ (2)<\/span>\n         std<span style=\"color: #555555\">::<\/span>dynamic_extent, std<span style=\"color: #555555\">::<\/span>dynamic_extent<span style=\"color: #555555\">&gt;<\/span>, \n         std<span style=\"color: #555555\">::<\/span>layout_left<span style=\"color: #555555\">&gt;<\/span> m2{myVec.data(), <span style=\"color: #FF6600\">4<\/span>, <span style=\"color: #FF6600\">2<\/span>};\n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot;m2.rank(): &quot;<\/span> <span style=\"color: #555555\">&lt;&lt;<\/span> m2.rank() <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n\n    <span style=\"color: #006699; font-weight: bold\">for<\/span> (std<span style=\"color: #555555\">::<\/span><span style=\"color: #007788; font-weight: bold\">size_t<\/span> i <span style=\"color: #555555\">=<\/span> <span style=\"color: #FF6600\">0<\/span>; i <span style=\"color: #555555\">&lt;<\/span> m2.extent(<span style=\"color: #FF6600\">0<\/span>); <span style=\"color: #555555\">++<\/span>i) {\n        <span style=\"color: #006699; font-weight: bold\">for<\/span> (std<span style=\"color: #555555\">::<\/span><span style=\"color: #007788; font-weight: bold\">size_t<\/span> j <span style=\"color: #555555\">=<\/span> <span style=\"color: #FF6600\">0<\/span>; j <span style=\"color: #555555\">&lt;<\/span> m2.extent(<span style=\"color: #FF6600\">1<\/span>); <span style=\"color: #555555\">++<\/span>j) {\n        std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> m2[i, j] <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39; &#39;<\/span>;  \n    }\n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n  }\n\n}\n<\/pre><\/div>\n\n\n\n<p>The <code>std::mdspan m<\/code> uses <code>std::layout_right<\/code> (line 1), the other <code>std::mdspan std::layout_left<\/code> (line 2). Thanks to class template argument deduction, the constructor call of <code>std::mdspan<\/code> (line 2) needs no explicit template arguments and is equivalent to the expression<code> std::mdspan m2{myVec.data(), 4, <\/code>2}.<\/p>\n\n\n\n<p>The output of the program shows the two different layout strategies:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"211\" height=\"280\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/09\/mdspanLayout.png\" alt=\"\" class=\"wp-image-8220\"\/><\/figure>\n\n\n\n<p>The following table presents an overview of <code>std::mdspan<\/code>&#8216;s interface.<\/p>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table><tbody><tr><td><strong>Functions of a <code>std::mdspan md<\/code><\/strong><\/td><td><strong>Description<\/strong><\/td><\/tr><tr><td><code>md[ind]<\/code><\/td><td>Access the <code>ind<\/code>-th element.<\/td><\/tr><tr><td><code>md.size<\/code><\/td><td>Returns the size of the multidimensional array.<\/td><\/tr><tr><td><code>md.rank<\/code><\/td><td>Returns the dimension of the multidimensional array.<\/td><\/tr><tr><td><code>md.extents(i)<\/code><\/td><td>Returns the size of the<code> i<\/code>-th dimension.<\/td><\/tr><tr><td><code>md.data_handle<\/code><\/td><td>Returns a pointer to the contiguous sequence of elements.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">What&#8217;s Next? <\/h2>\n\n\n\n<p>C++20 does not provide concrete coroutines, but C++20 provides a framework for implementing coroutines. This changes with C++23.<code> std::generator<\/code> is the first concrete coroutine.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A std::mdspan is a non-owning multidimensional view of a contiguous sequence of objects. The contiguous sequence of objects can be a plain C-array, a pointer with a size, a std::array, a std::vector, or a std::string. Often, this multidimensional view is called a multidimensional array. The number of dimensions and the size of each dimension determine [&hellip;]<\/p>\n","protected":false},"author":21,"featured_media":8210,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[378],"tags":[],"class_list":["post-8208","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c-23"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/8208","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/comments?post=8208"}],"version-history":[{"count":15,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/8208\/revisions"}],"predecessor-version":[{"id":9994,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/8208\/revisions\/9994"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/8210"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=8208"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=8208"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=8208"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}