You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建起始索引非0的std::mdspan以直接用原始维度值访问元素?

可以直接用year, month, ZipCode访问的std::mdspan实现方案

当然可以,有两种主流实现方式,分别适配不同的C++版本:

方法一:C++23原生支持(使用std::strided_layout)

利用C++23引入的std::strided_layout,可以直接为每个维度指定起始索引偏移和元素步长,让mdspan直接识别原始的年份、月份、邮编数值:

#include <mdspan>
#include <array>

// 假设vec是已解析好的std::vector<int>
auto vec = parse_binary_file();

// 定义各维度的范围:年份1913-2023(100个)、月份1-12(12个)、邮编20000-20999(1000个)
using Extents = std::extents<std::size_t, 100, 12, 1000>;

// 创建带偏移的布局:每个维度的起始索引、元素步长
auto layout = std::strided_layout<Extents>(
    std::array<std::size_t, 3>{1913, 1, 20000},  // 各维度的起始值
    std::array<std::size_t, 3>{12 * 1000, 1000, 1}  // 各维度的元素步长
);

// 构造支持直接索引的mdspan
auto my_md_span = std::mdspan<int, Extents, decltype(layout)>(vec.data(), layout);

// 直接使用原始数值访问
int count = my_md_span[1913, 1, 20000];  // 正确获取对应组合的居民数量

这种方式完全依赖C++23标准,需要编译器支持(如GCC 12+、Clang 15+、MSVC 2022+)。

方法二:兼容C++17及以上(封装轻量视图)

如果无法使用C++23,可以封装一个简单的包装类,自动处理索引偏移转换,同时保留mdspan的轻量特性:

#include <mdspan>
#include <tuple>

struct InhabitantsView {
    std::mdspan<int, std::extents<std::size_t, 100, 12, 1000>> inner_span;

    // 支持多参数调用(更直观)
    int& operator()(int year, int month, int zip_code) {
        return inner_span[year - 1913, month - 1, zip_code - 20000];
    }

    // 支持tuple索引(可选)
    int& operator[](const std::tuple<int, int, int>& idx) {
        auto [year, month, zip] = idx;
        return inner_span[year - 1913, month - 1, zip - 20000];
    }
};

// 使用方式
auto original_span = std::mdspan(vec.data(), 100, 12, 1000);
InhabitantsView my_view{original_span};

// 直接访问
int count = my_view(1913, 1, 20000);
// 或用tuple索引
// int count = my_view[{1913, 1, 20000}];

这种方式兼容性更强,且不会带来额外性能开销,本质只是对原始mdspan的一层薄封装。

内容的提问来源于stack exchange,提问作者Porsche9II

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 11:11:12