使用std::span<std::span<uint8_t>>
我用了很多C ++ 20的新功能:std::span<T>。这对于编写通常带有指针和大小的函数很有用。
#include <array>
#include <span>
#include <vector>
std::vector<uint8_t> v1 {1,2,3,4,5};
std::array<uint8_t, 4> v2 {1,2,3,4};
uint8_t v3[3] = {1,2,3};
void f(std::span<uint8_t> arr){
...
}
/// call f with v1 or v2 or v3
f(v1);
f(v2);
f(v3);
现在,我想要一个将跨度作为参数的函数。
std::vector<std::array<uint8_t,10>> v1;
v1.push_back({0, 1, 2, 3, 4, 5, 6, 7, 8, 9});
v1.push_back({0, 1, 2, 3, 4, 5, 6, 7, 8, 9});
v1.push_back({0, 1, 2, 3, 4, 5, 6, 7, 8, 9});
void f(std::span<std::span<uint8_t, 10>> arr){
...
}
f(v1);
不幸的是,这根本没有编译。这将是一种处理二维数组的方法。
编译错误:
<source>:21:1: error: no matching function for call to 'f'
f(v1);
^
<source>:8:6: note: candidate function not viable: no known conversion from 'std::vector<std::array<uint8_t, 10>>' (aka 'vector<array<unsigned char, 10>>') to 'std::span<std::span<uint8_t, 10>>' (aka 'span<span<unsigned char, 10>>') for 1st argument
void f(std::span<std::span<uint8_t, 10>> arr){
^
1 error generated.
ASM generation compiler returned: 1
<source>:21:1: error: no matching function for call to 'f'
f(v1);
^
<source>:8:6: note: candidate function not viable: no known conversion from 'std::vector<std::array<uint8_t, 10>>' (aka 'vector<array<unsigned char, 10>>') to 'std::span<std::span<uint8_t, 10>>' (aka 'span<span<unsigned char, 10>>') for 1st argument
void f(std::span<std::span<uint8_t, 10>> arr){
^
1 error generated.
Execution build compiler returned: 1
您知道如何在不使用原始指针的情况下使其工作吗?
回答
这不起作用,因为向量不包含跨度。这个错误有点类似于试图将一个int[x][y]into 函数传递给 accepting int**。
你应该:
- 使用 a
std::span<std::array<uint8_t,10>>访问向量
void f2(std::span<std::array<uint8_t,10>> arr)
- 或者将向量转换为跨度范围。
auto to_span = [](auto& arr) -> std::span<uint8_t, 10> { return {arr}; }; auto span_range = std::ranges::transform_view(v1, to_span); std::vector v2(std::begin(span_range), std::end(span_range)); f(v2);
它不会总是数组的向量
如果您有时想使用一种类型的参数,有时又想使用另一种类型的参数,那么也许您应该定义一个函数模板:
template<class Range> void f3(Range& range)
但我正在寻找另一种方式,因为它有一定的成本 O(N)。
您已经支付了O(N) * O(M)创建矢量的费用。上面的那个O(N)不太可能很重要。
THE END
二维码