标签: std-span

什么是"跨度",什么时候应该使用?

最近我有建议span<T>在我的代码中使用's,或者在网站上看到了一些使用span's - 应该是某种容器的答案.但是 - 我在C++标准库中找不到类似的东西.

那么这个神秘的是什么span<T>,以及为什么(或什么时候)使用它是一个好主意,如果它是非标准的?

c++ c++-faq cpp-core-guidelines c++20 std-span

202
推荐指数
3
解决办法
4万
查看次数

当一个跨度是另一个跨度的子跨度时,C++ 是否允许在 std::span::iterators 之间进行比较?

一般来说,C++ 不允许比较不同容器之间的迭代器。例如:

int main() {
  std::vector<int> v = {1, 2, 3};
  std::vector<int> w = {4, 5, 6};
  std::cout << v.end() == w.end() << std::endl;  // undefined!
}
Run Code Online (Sandbox Code Playgroud)

但是对于使用 创建的子跨度来说也是如此吗std::span::subspan()?例如:

int main() {
  int a[4] = { 1, 2, 3, 4};
  std::span<int> s(a);
  std::span<int> t = s.subspan(1, 2);
  std::cout << t.begin() - s.begin() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

这会打印1,这是预期的,因为内部迭代器可能只是指向底层数组的指针。问题是:该标准能否保证其正常工作?

如果是这样,更一般地说,我是否还可以比较来自内存中同一连续对象的任何跨度的迭代器?例如:

int main() {
  int a[5] = { 1, 2, 3, 4, 5};
  std::span<int> s(a);
  std::cout << (s.subspan(1, 1).end() < …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer c++20 std-span

16
推荐指数
1
解决办法
438
查看次数

为什么span的array和std :: array构造函数与其容器构造函数不同

我一直在研究std::span在Godbolt上使用clang干线和libc ++ 的最新规范,并发现一些令人困惑的构造函数。

特别是,我从一个普通的旧数组中发现了构造函数,并且a std::array与其他容器不同。

例如,以下代码似乎可以编译:

std::vector<int*> v = {nullptr, nullptr};
std::span<const int* const> s{v};
Run Code Online (Sandbox Code Playgroud)

但是,这不是:

std::array<int*, 2> a = {nullptr, nullptr}; 
std::span<const int* const> s{a};
Run Code Online (Sandbox Code Playgroud)

这似乎与cppreference.com上描述构造函数的方式保持一致,我只是在努力理解为什么是这种情况。有人可以照亮吗?

c++ c++20 std-span

14
推荐指数
1
解决办法
323
查看次数

为什么 std::span 缺少比较运算符?

不是std::span设计为轻量参考的子区域std::vector/ std::array/普通数组和相似吗?它不应该在其 API 中也包含比较运算符,以与它们保持一致吗?排除背后的原因是什么?

注意:通过比较运算符,我的意思是完整的集合 ( <, <=, ...) 或宇宙飞船<=>

c++ std c++20 std-span

13
推荐指数
1
解决办法
561
查看次数

为什么我特别应该将 std::span 而不是 std::vector&amp; 传递给函数?

我知道这可能与问题重叠:什么是 \xe2\x80\x9cspan\xe2\x80\x9d 以及我何时应该使用它?,但我认为问题的这个特定部分的答案相当令人困惑。一方面,有这样的引用:

\n
\n

如果您有一个标准库容器(或 Boost 容器等),并且您知道它最适合您的代码,请不要使用它。它无意取代其中任何一个。

\n
\n

但在同一个答案中,出现了这样的说法:

\n
\n

当您希望数据在内存中连续时,是将 const vector& 传递给函数的合理替代方案。再也不用被 C++ 大师骂了!

\n
\n

那么我没有到达哪一部分呢?我什么时候会这样做:

\n
void foo(const std::vector<int>& vec) {}\n
Run Code Online (Sandbox Code Playgroud)\n

而这是什么时候呢?

\n
void foo(std::span<int> sp) {}\n
Run Code Online (Sandbox Code Playgroud)\n

还有,这会不会

\n
void foo(const std::span<int> sp) {}\n
Run Code Online (Sandbox Code Playgroud)\n

有什么意义吗?我认为不应该,因为 astd::span只是 a struct,包含指针和长度。但是,如果它不能阻止您更改std::vector作为参数传递的值,那么它如何替换const std::vector<T>&

\n

c++ vector c++20 std-span

13
推荐指数
1
解决办法
8615
查看次数

返回条件`range_expression`

根据某种条件在几个已知范围之一上进行迭代的最有效方法是什么?

二进制条件的伪代码:

for element in (condition ? range_a : range_b)
  // do work
Run Code Online (Sandbox Code Playgroud)

这个“示例”显示了我使用基于范围的for循环的意图但由于std::initializer_list具有参考语义,因此无法使用。

for element in (condition ? range_a : range_b)
  // do work
Run Code Online (Sandbox Code Playgroud)

产量: warning: returning address of local temporary object [-Wreturn-stack-address]

在运行时,我可以返回a,std::vector但这将涉及在每次调用时构造一个新的向量:

constexpr auto some_range(bool c) -> std::initializer_list<int> {
  if (c) {
    return {1,2};
  } else {
    return {3, 4, 5};
  }
}

bool cond = true; // false

for(auto x : some_range(cond)) {
  // things
}
Run Code Online (Sandbox Code Playgroud)

我可以使用的固定大小std::array …

c++ constexpr c++11 c++14 std-span

11
推荐指数
1
解决办法
205
查看次数

为什么在传递 std::vector 时不能为 std::span&lt;T&gt; 推导 T ?

在以下 C++20 代码中,将 a 传递std::vector给带有参数的模板化函数std::span<T>会失败,因为显然编译器无法推导出模板参数。我已经用 GCC、Clang 和 MSVC 尝试过了;全部失败。

像这样调用有效:f3(std::span(vi))f3(std::span(vp))

我想知道为什么会失败,因为在我的理解中,std::vector是一个范围,并且std::span有范围的推导指南。

#include <memory>
#include <vector>
#include <span>

void f1(std::span<int> s)
{
}

void f2(std::span<std::shared_ptr<int>> s)
{
}

template<typename T>
void f3(std::span<T> s)
{
}

int main(int argc, char* argv[])
{
    std::vector<int> vi;
    std::vector<std::shared_ptr<int>> vp;

    f1(vi);
    f2(vp);
    f3(vi); // ERROR: no matching function for call to 'f3'
    f3(vp); // ERROR: no matching function for call to …
Run Code Online (Sandbox Code Playgroud)

c++ templates template-argument-deduction c++20 std-span

11
推荐指数
2
解决办法
434
查看次数

std :: cspan发生了什么?

std::span已被选入C ++ 20。我假设与一起std::span将有一个方便的别名,定义如下:

template <class T, size_t Extent = dynamic_extent>
using cspan = span<const T, Extent>;
Run Code Online (Sandbox Code Playgroud)

对我来说,这似乎是一个非常方便的别名。我可能cspan会比使用更多span!根据cppreferencecspan不存在。有一个提到cspan本文中这似乎暗示,是在一些点的标准。我找不到其他提及。

那怎么了cspan?它被删除了吗?它曾经存在过吗?

c++ language-lawyer c++20 std-span

9
推荐指数
1
解决办法
271
查看次数

什么是 mdspan,它的用途是什么?

在过去一年左右的时间里,我注意到 StackOverflow 上有一些与 C++ 相关的答案mdspan,但我从未在 C++ 代码中真正看到过这些答案。我尝试在 C++ 编译器的标准库目录和C++ 编码指南中查找它们- 但找不到它们。我确实找到了std::span;我猜它们是相关的——但是如何呢?添加“md”代表什么?

请解释一下这个神秘实体的用途,以及我何时需要使用它。

c++ c++-faq std-span mdspan

9
推荐指数
1
解决办法
2480
查看次数

为什么std :: span缺少size_type?

我一直在更新使用homebrew span类的旧代码,使之更符合C ++ 20的要求,std::span并且由于std::span没有size_type和有,我遇到了编译错误index_type。关于是否index_type应该签名已经发生了巨大的变化,但是为什么要跳过size_type呢?这会破坏期望容器(或类似容器的对象)具有的通用代码size_type

c++ c++20 std-span

8
推荐指数
2
解决办法
549
查看次数