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...
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)