我曾经使用指南支持库中的 gsl::span 工作了一段时间。使用 gsl::span,可以定义一个采用静态范围并使用动态范围的 gsl::span 调用它的函数,例如
void f(gsl::span<int, 5> s) { }
...
std::vector<int> v(100);
f(gsl::make_span(v).subspan(42, 5)); // Works
Run Code Online (Sandbox Code Playgroud)
将代码移植到 std::span 后,我注意到这不再可能:
void f(std::span<int, 5> s) { }
...
std::vector<int> v(100);
f(std::span(v).subspan(42, 5)); // Does not work
Run Code Online (Sandbox Code Playgroud)
这种差异有什么原因吗?是否有任何推荐的方法可以将具有动态范围的 std::span 转换为具有固定范围的 std::span?当然,在调用函数时可以创建一个固定范围的新跨度:
f(std::span<int, 5>(&v[42], 5));
Run Code Online (Sandbox Code Playgroud)
但是,我认为“subspan”变体的可读性要好得多,它以更好的方式表达了意图,并且允许在调试版本中进行适当的范围检查。
这种差异有什么原因吗?
P1976 详细介绍了这一点。Fixed-extent spans 有显式的构造函数来尝试减轻未定义的行为,因此std::span<int>(的类型std::span(v).subspan(42, 5))不能转换为std::span<int, 5>.
是否有任何推荐的方法可以将具有动态范围的 std::span 转换为具有固定范围的 std::span?
如果偏移量和计数都是常量表达式(在这种情况下为真),则可以使用 的其他重载subspan():
f(std::span(v).subspan<42, 5>());
Run Code Online (Sandbox Code Playgroud)
这种重载以它的方式存在,因此您可以安全地获取固定范围跨度的固定范围子跨度,但是当想要获取动态范围跨度的固定范围子跨度时不太理想,理想情况下我们只是有想要的std::span(v).subspan<5>(42)。
对于这种情况,您可以改为first()与 结合使用subspan:
f(std::span(v).subspan(42).first<5>());
Run Code Online (Sandbox Code Playgroud)
稍微长一点,但完成工作。
或者你可以全力以赴并使用构造函数:
f(std::span<int, 5>(std::span(v).subspan(42, 5)));
f(std::span<int, 5>(v.data() + 42, 5));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
408 次 |
| 最近记录: |