标签: std-span

为什么 std::span 缺少 cbegin 和 cend 方法?

为什么std::span只有beginandend方法而不是它们的常量迭代器对应物cbeginand cend?(标准

我还注意到,我能找到的关于 span 的建议确实对cbeginand有定义cendP0122R7。为什么被删除了?

c++ iterator c++20 std-span

7
推荐指数
1
解决办法
228
查看次数

如何使用 std span 进行边界检查?

std::vector几乎所有其他容器都有一种非常方便的边界检查方法:at(). std::span显然没有那个。

c++ outofrangeexception c++20 std-span

6
推荐指数
1
解决办法
1700
查看次数

从 C 字符串数组创建 string_views 的范围

给定某个函数void func(std::span<std::string_view>),如何const char**以最有效的方式为该函数提供原始 C 字符串数组?

据我了解,这应该是可能的,因为std::string_view可以从 C 字符串std::span构造并且可以从指针 + 大小构造,而无需任何复制。但是,我似乎无法弄清楚正确的语法。

下面是一些std::vector<std::string_view>通过迭代字符串数组中的每个字符串来创建一个的最小代码:

#include <iostream>
#include <string>
#include <span>
#include <vector>

static void func(std::span<std::string_view> strings)
{
    // Just print the strings...
    std::cout << "strings:\n";
    for (const auto& str : strings)
        std::cout << str << "\n";
    std::cout << std::endl;
}

int main()
{
    // Raw C string array
    const char* raw_strings[3] = {
        "This is a string",
        "This is also a string",
        "And …
Run Code Online (Sandbox Code Playgroud)

c++ string-view c++20 std-span

6
推荐指数
1
解决办法
463
查看次数

为什么我不能从迭代器构造一个 std::span ?

考虑一个大内存容器。在这个简单的例子中std::vector<int>

std::vector v = { 0, 1, 2, 3, 4, 5 };
Run Code Online (Sandbox Code Playgroud)

std::span允许我创建一个轻量级的内存视图。现在我想简单地打印跨度:

template<typename T>
void print(std::span<T> span) {
    std::cout << '[';
    if (span.size())
        std::copy(span.begin(), span.end() - 1, std::ostream_iterator<int>(std::cout, ", "));

    std::cout << span.back() << "]\n";
}

int main() {
    std::vector v = { 0, 1, 2, 3, 4, 5 };

    print(std::span{ v });
}

Run Code Online (Sandbox Code Playgroud)

输出:

[0, 1, 2, 3, 4, 5]
Run Code Online (Sandbox Code Playgroud)

现在我想制作子集(这是std::span实际作为视图变得有用的地方)。我可以用迭代器来指定我的范围,并调用此构造函数(3)std::span

template< class It, class End >
explicit(extent != std::dynamic_extent) …
Run Code Online (Sandbox Code Playgroud)

c++ iterator c++20 std-span

6
推荐指数
1
解决办法
523
查看次数

为什么C++20知道如何散列string_view,但不知道如何散列span&lt;char&gt;?

我最好的猜测是,委员会要么忘记了这个用例,要么不想使用概念/要求将类型限制span为可以安全散列的东西(POD,无填充),或者他们不想要半解决方案(等待反射) )...

如果有人对这里感兴趣,可以使用带有无用错误消息和代码的godbolt链接,但我认为我的问题很清楚,没有任何代码。

#include <span>
#include <unordered_set>
#include <string_view>
int main() {
    std::hash<std::string_view> h1;
    std::hash<std::span<char>> h2; // error here
}
Run Code Online (Sandbox Code Playgroud)

注意:我知道 C++std::库在哈希方面缺乏,例如它不能哈希std::pair<int,int>,但我的问题特别是关于std::span.

c++ string-view c++20 std-span

6
推荐指数
1
解决办法
738
查看次数

跨度传播const吗?

标准容器传播const。也就是说,如果容器本身是const,则它们的元素自动为const。例如:

const std::vector vec{3, 1, 4, 1, 5, 9, 2, 6};
ranges::fill(vec, 314); // impossible

const std::list lst{2, 7, 1, 8, 2, 8, 1, 8};
ranges::fill(lst, 272); // impossible
Run Code Online (Sandbox Code Playgroud)

内置数组还传播const:

const int arr[] {1, 4, 1, 4, 2, 1, 3, 5};
ranges::fill(arr, 141); // impossible
Run Code Online (Sandbox Code Playgroud)

但是,我注意到std::span(大概)不会传播const。最小的可重现示例:

#include <algorithm>
#include <cassert>
#include <span>

namespace ranges = std::ranges;

int main()
{
    int arr[] {1, 7, 3, 2, 0, 5, 0, 8};

    const std::span spn{arr};
    ranges::fill(spn, 173);               // this compiles

    assert(ranges::count(arr, …
Run Code Online (Sandbox Code Playgroud)

c++ const c++20 std-span

5
推荐指数
2
解决办法
196
查看次数

将 std::span 分配给 std::vector 的最简单方法

我想这样做

#include <vector>
#include <span>

struct S
{
    std::vector<int> v;
    void set(std::span<int> _v)
    {
        v = _v;
    }
};
Run Code Online (Sandbox Code Playgroud)

但它不编译。有哪些替代方案?

c++ stdvector c++-standard-library c++20 std-span

5
推荐指数
1
解决办法
325
查看次数

将 nullptr 转换为 std::span

我有一个const z* zs = nullptr;

\n

我想转换zsstd::span

\n

当我尝试这样做时,std::span<const z>(zs) 我收到一条错误消息

\n
\n

错误:没有匹配的函数可调用 \xe2\x80\x98std::span::span(const z* const&)\xe2\x80\x99

\n
\n

如何转换为 zsstd::span

\n

我试过std::span<const z>(zs[0])了,好像可以编译。这种方式正确吗?

\n

c++ nullptr std-span

5
推荐指数
2
解决办法
1319
查看次数

从固定大小的 std::span 创建固定大小的 std::array 的惯用方法是什么?

std::array<uint8_t,N>我正在尝试从 a创建 a,std::span<uint8_t,N>但我找不到一种没有memcpy、或 的方法来执行此操作std::copy,或者std::ranges::copy这不能保护我免受目标数组大小的错误指定。

#include <algorithm>
#include <array>
#include <iostream>
#include <span>

int main(int argc, char **argv) {
  constexpr size_t N = 10;
  std::array<uint8_t, N> original;
  std::span span(original); // of type std::span<uint8,N>

  std::array copy1(span);                               // does not work
  std::array<uint8_t, N> copy2(span);                   // does not work
  std::array<uint8_t, N> copy3(begin(span), end(span)); // does not work


  // ugly stuff that works, but does not protect me if I specify wrong array size
  constexpr size_t …
Run Code Online (Sandbox Code Playgroud)

c++ stdarray c++20 std-span

5
推荐指数
2
解决办法
305
查看次数

如何将 `const std::vector&lt;T*&gt;` 转换为 `std::span&lt;const T*&gt;`

标题。

我正在实现这个类:

#include <span>
#include <vector>

class MyClass {
public:
    std::span<int *> numbers(void) {
        return m_numbers;
    }

    std::span<const int *> cnumbers(void) const {
        // What to do here?
    }

private:
    std::vector<int *> m_numbers;
};
Run Code Online (Sandbox Code Playgroud)

我的第一次尝试是使用非常量函数中展示的自动转换(我相信这与 相关std:decay?我不太明白)。

return m_numbers
Run Code Online (Sandbox Code Playgroud)

这无法编译,没有已知的转换。

我发现的一种实现是这样的:

return std::span(m_numbers.begin(), m_numbers.end());
Run Code Online (Sandbox Code Playgroud)

这会返回一个std::span<int * const>,但这并不完全是我想要的。这种使用的变体cbegin似乎没有帮助。

我的目标是 c++20

c++ std c++20 std-span

5
推荐指数
1
解决办法
220
查看次数