c++stdmdspan

How to store std::mdspan?


If I want to store an instance of std::mdspan in a structure to be passed to a function, is there a way to do so without converting the client function to a template?

In this code demo:

#include <iostream>
#include <vector>
#include <mdspan>

int* dummy;

struct Container {
    decltype(std::mdspan(dummy, 0, 0)) array2d;
};

void foo(Container cont) {
    std::cout << cont.array2d[std::array{ 1, 1 }];
}

int main()
{
    std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7 };

    auto array2d = std::mdspan(v.data(), 2, 4);

    Container container;

    container.array2d = array2d;

    foo(container);
}

I can't see how to avoid this dummy object to get the type of the std::mdspan and if it is possible to avoid using decltype in Container at all.

Replacement of decltype with

std::mdspan<float*,int,int> array2d;

doesn't work with:

Z:/compilers/msvc/14.41.33923-14.41.33923.0/include\mdspan(1075): error C2903: 'mapping': symbol is neither a class template nor a function template
Z:/compilers/msvc/14.41.33923-14.41.33923.0/include\mdspan(1075): note: the template instantiation context (the oldest one first) is
<source>(6): note: see reference to class template instantiation 'std::mdspan<float *,int,int,std::default_accessor<float *>>' being compiled
Z:/compilers/msvc/14.41.33923-14.41.33923.0/include\mdspan(1159): note: see reference to class template instantiation 'std::_Mdspan_mapping_base<_Extents,_LayoutPolicy>' being compiled
        with
        [
            _Extents=int,
            _LayoutPolicy=int
        ]
etc...

Solution

  • You only need to fill the first 2 template arguments of mdspan, the first is the underlying type (here int) the second is its extents.

    If you know the mdspan size at compile time you can code it into the type, which makes it faster std::extents<size_t, 2, 4> (2x4 matrix) ( size_t here means indexing is done using size_t).

    If you only know the size at runtime then use dynamic extents to determine the extents at runtime, you only need to specify the number of dimensions std::dextents<size_t, 2> (2d matrix) ( the d in dextents for dynamic)

    struct Container {
        std::mdspan<int, std::dextents<size_t, 2>> array2d;
    };
    

    If one of the two dimensions is known at compile time, then you can specify that to make it faster std::extents<size_t, std::dynamic_extent, 4> (Nx4 matrix)