如何在非模板函数中存储并传递std::mdspan至结构体?
关于std::mdspan存储到结构体及非模板函数传递的问题
问题点
- 能否将std::mdspan实例存入结构体并传递给函数,且无需将目标函数改为模板实现?
- 当前代码通过dummy对象配合
decltype获取std::mdspan类型,是否有更直接的方式规避这种写法? - 尝试直接指定
std::mdspan<float*,int,int>类型时触发编译错误,错误信息如下:
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...
原始代码示例
#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); }
解答
1. 直接指定类型报错的原因
std::mdspan的模板参数不是直接填维度数值,第二个模板参数要求是符合Extents概念的类型(比如std::extents或std::dextents),而非原始的int。你直接传入两个int,编译器会把它们当成Extents和LayoutPolicy模板参数,而int不满足这两个模板参数的要求,导致内部mapping相关模板实例化失败,触发编译错误。
2. 规避dummy+decltype的写法
直接明确指定std::mdspan的正确模板参数即可:
- 动态维度(运行时确定大小):用
std::dextents<int, N>,其中N是维度数。比如二维动态数组的类型是std::mdspan<int*, std::dextents<int, 2>> - 固定维度(编译时确定大小):用
std::extents<int, D1, D2,...>,比如固定2行4列的数组类型是std::mdspan<int*, std::extents<int, 2, 4>>
修改后的Container结构体示例:
struct Container { // 动态二维int数组的mdspan类型 std::mdspan<int*, std::dextents<int, 2>> array2d; };
3. 非模板函数传递的可行性
完全可以。只要结构体中mdspan的类型是明确固定的,函数foo直接接受Container类型即可,不需要改成模板函数。原始代码中Container的类型已经通过decltype推导确定,所以foo可以正常工作;修改为直接指定类型后,同样可以用非模板函数传递。
完整修改后的代码
#include <iostream> #include <vector> #include <mdspan> #include <array> struct Container { std::mdspan<int*, std::dextents<int, 2>> array2d; }; void foo(Container cont) { std::cout << cont.array2d[std::array{1, 1}] << std::endl; } 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); }
内容的提问来源于stack exchange,提问作者Damir Tenishev
相关产品推荐
相关产品推荐

