标签: std-span

为什么std :: span一个指针+大小而不是两个迭代器

看来std::spanC ++ 20中的定义与

template<class T>
class span
     {
     T* begin;
     size_t count;
     };
Run Code Online (Sandbox Code Playgroud)

并不是

template<class Iter>
class span
     {
     Iter begin;
     Iter end;
     };
Run Code Online (Sandbox Code Playgroud)

哪个更通用(可与std :: list,std :: map等配合使用)?

c++ c++20 std-span

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

std::span 迭代器可以比创建它们的 span 对象寿命更长吗?

换句话说,反过来,std::span迭代器在span实例被销毁后会失效吗?

我有一个向量需要用不同的布局进行迭代。我试图std::span避免编写大量迭代器样板或引入外部库依赖项。简化示例:

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

template <size_t N>
struct my_view {
  std::vector<int> vec;

  auto as_span() {
    return std::span<int[N]>((int(*)[N])vec.data(), vec.size() / N);
  }

  auto begin() {
    return as_span().begin();
  }

  auto end() {
    return as_span().end();
  }
};

int main() {
  std::vector vec {1, 2, 3, 4, 5, 6};
  my_view<2> pairs {std::move(vec)};
  for (auto pair : pairs) {
    std::cout << pair[0] << " " << pair[1] << std::endl;
  }
  my_view<3> triplets {std::move(pairs.vec)};
  for (auto triplet : …
Run Code Online (Sandbox Code Playgroud)

c++ iterator lifetime c++20 std-span

4
推荐指数
1
解决办法
622
查看次数

从无符号字符的 std::span 创建 std::string

我正在使用一个 C 库,它使用各种固定大小的unsigned char数组,不带空终止符作为字符串。

我已经将它们转换为std::string使用以下函数:

auto uchar_to_stdstring(const unsigned char* input_array, int width) -> std::string {
  std::string temp_string(reinterpret_cast<const char*>(input_array), width);
  temp_string.erase(temp_string.find_last_not_of(' ') + 1);

  return temp_string;
}
Run Code Online (Sandbox Code Playgroud)

除了使用reinterpret_cast、需要传递数组大小以及我将数组衰减为指针之外,它工作得很好。我试图通过使用 来避免所有这些问题std::span

使用的函数std::span如下所示:

auto ucharspan_to_stdstring(const std::span<unsigned char>& input_array) -> std::string {
  std::stringstream temp_ss;

  for (const auto& input_arr_char : input_array) {
    temp_ss << input_arr_char;
  }

  return temp_ss.str();
}
Run Code Online (Sandbox Code Playgroud)

该函数运行良好,使其他一切变得更简单,而无需跟踪 C 数组的大小。但是,通过一些基准测试(使用nanobench )进一步挖掘表明,新函数比经典方法慢很多倍reinterpret_cast。我的假设是基于 - 的函数for中的循环std::span是这里效率低下的。

我的问题:是否有更有效的方法将固定大小的无符号字符 C 数组从 …

c++ stdstring c++20 std-span

4
推荐指数
1
解决办法
3941
查看次数

std::span 中 std::dynamic_extent 的用途是什么

我知道std::span是静态的。它只是一堆向量/数组/等的视图。元素。

我看到span的构造函数,好像std::dynamic_extent是在4-6中使用的。但在这些构造函数中,大小有一个必需的模板参数 - std::size_t N。对我来说,这意味着大小/计数/长度在编译时是已知的。那么到底是什么std::dynamic_extent

c++ std std-span

4
推荐指数
1
解决办法
403
查看次数

如何制作跨度跨度

C++20std::span是一个非常好的编程接口。但是似乎没有一种简单的方法来获得跨度。这是我想要做的:

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

void print(std::span<std::span<wchar_t>> matrix) {
  for (auto const& str : matrix) {
    for (auto const ch : str) {
      std::wcout << ch;
    }
    std::wcout << '\n';
  }
}

int main() {
  std::vector<std::wstring> vec = {L"Cool", L"Cool", L"Cool"};
  print(vec);
}
Run Code Online (Sandbox Code Playgroud)

这不编译。我该怎么做?

c++ c++20 std-span

3
推荐指数
1
解决办法
290
查看次数

从 std::span&lt;T&gt; 中删除第一个元素的方法是什么?

在阅读std::span的文档时,我发现没有方法可以从std::span<T>.

您能建议一种方法来解决我的问题吗?

我的问题的大局(我在另一个问题中问:How to instantiate a std::basic_string_view with custom class T,我得到 is_trivial_v<_CharT> 断言错误)是我想要一个std::basic_string_view<Token>,而这Token不是一个微不足道的问题类,所以我不能使用std::basic_string_view,有人建议我改用std::span<Token>

由于basic_string_view有一个名为删除第一个元素的方法remove_prefix,而我也需要此类函数,因为我想用作std::span<Token>解析器输入,因此令牌将被匹配,并一个接一个地消耗。

谢谢。

编辑 2023-02-04

我尝试派生一个名为Spanfrom的类std::span,并添加remove_prefix成员函数,但看起来我仍然存在构建问题:

#include <string_view>
#include <vector>
#include <span>


// derived class, add remove_prefix function to std::span
template<typename T>
class Span : public std::span<T>
{
public:
    // Inheriting constructors
    using std::span<T>::span;

    // add a public function which is similar to …
Run Code Online (Sandbox Code Playgroud)

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

3
推荐指数
1
解决办法
692
查看次数

如何使用 span 来包装命令行参数

即将推出的 C++20 的这种使用是否std::span正确并且没有开销来包装命令行参数?

#include <iostream>
#include <span>

int main(int argc, const char* argv[])
{
    for (auto s : std::span { argv, static_cast<std::size_t>(argc) })
      std::cout << s << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

如果它是正确的,我可以进一步使用 withstd::string_view吗?

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

2
推荐指数
1
解决办法
1532
查看次数

如何使类与采用范围的 std::span 构造函数兼容?

我希望能够将我的自定义容器传递给这个std::span构造函数:

template< class R >
explicit(extent != std::dynamic_extent)
constexpr span( R&& range );
Run Code Online (Sandbox Code Playgroud)

我需要向自定义类添加什么,以使其满足能够将其传递给std::span接收范围的构造函数的要求?

例如,std::vector我们可以这样做:

std::vector<int> v = {1, 2, 3};
auto span = std::span{v};
Run Code Online (Sandbox Code Playgroud)

我已经将这些添加到我的自定义类中:

Type* begin()
{
    return m_Data;
}

Type* end()
{
    return m_Data + m_Length;
}

const Type* data() const
{
    return m_Data;
}

size_t size() const
{
    return m_Length;
}
Run Code Online (Sandbox Code Playgroud)

...这反过来又允许我使用基于范围的循环,std::data(my_container)以及std::size(my_container). 我还缺少什么才能将容器传递给std::span构造函数?是否需要实现更复杂的迭代器?

c++ c++20 std-span std-ranges

2
推荐指数
1
解决办法
934
查看次数

是否可以恢复“std::span”中元素的实际索引?

我有一个带有成员变量的类std::vector。我还有一个成员函数,它采用std::vector由两个size_t参数指定的连续范围,并对其执行一些操作。

class MyClass {
    std::vector<int> objects;

public:

    void func(size_t start_index, size_t end_index); 
}
Run Code Online (Sandbox Code Playgroud)

现在,我想size_t用单个参数替换两个std::span参数,以提高安全性、可读性和可维护性。然而,有一个障碍:在我的函数中,我需要能够恢复原始std::vector. 就像这样,我需要能够找到std::span原始数组中的开始位置。有没有办法做到这一点?如果没有,那么我是否别无选择,只能使用我原来笨重的设计?

objects.begin()(我最初尝试通过从我拥有的参数begin()的迭代器中减去来恢复第一个索引std::span,但这导致了编译错误。)

c++ stdvector c++20 std-span

2
推荐指数
1
解决办法
94
查看次数

是否可以从 C++20 中的视图构造一个 `std::span`?

此示例程序无法编译,因为transform_view无法转换为std::span

class Foo {
private:
    std::vector<std::string> strings = { "a", "b", "c" };

public:
    std::span<const char*> getStrings() {
        return strings | std::views::transform([](const std::string& str) { return str.c_str(); });
    }
};

int main() {
    Foo foo;
    auto strings = foo.getStrings();

    for (auto s : strings)
        std::cout << s << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

我知道还不可能构造容器(如std::vector),但是我不太明白,为什么不能从中构造 a std::span。我找到了这个答案,即目前唯一可以从任意范围构建的容器是std::span,所以我希望上面的例子能够工作。

有没有办法从范围创建跨度?或者有没有其他方法可以从方法返回通用视图,而不使用auto(虚拟方法不允许)?

c++ c++20 std-span std-ranges

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

为什么逻辑常量只能添加到 const 指针的 std::span 中?

std::span考虑这段代码,它尝试为原始指针向量创建各种对象。

#include <vector>
#include <span>

int main()
{
    struct S {};
    std::vector<S*> v;
    std::span<S*> span1{v};
    std::span<S* const> span2{v};
    std::span<const S* const> span3{v};
    std::span<const S*> span4{v};
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

span3编译正常,但span4失败并出现以下错误:

<source>: In function 'int main()':
<source>:58:32: error: no matching function for call to 'std::span<const main()::S*>::span(<brace-enclosed initializer list>)'
   58 |     std::span<const S*> span4{v};
      |                                ^
In file included from /opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/ranges:45,
                 from <source>:5:
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/span:231:9: note: candidate: 'template<class _OType, long unsigned int _OExtent>  requires (_Extent == std::dynamic_extent || _OExtent == …
Run Code Online (Sandbox Code Playgroud)

c++ c++20 std-span

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

如何从 std::iota 构造跨度?

以下作品:

#include <vector>
#include <ranges>

int main() {
    auto view = std::vector<int>{0,1,2,3,4};
    auto s = std::span{view.begin(), view.end()};
    std::vector test(view.begin(), view.end());
}
Run Code Online (Sandbox Code Playgroud)

但这并不:

#include <vector>
#include <ranges>

int main() {
    auto view = std::ranges::iota_view{0, 1000};
    auto s = std::span{view.begin(), view.end()};
    std::vector test(view.begin(), view.end());
}
Run Code Online (Sandbox Code Playgroud)

问题是,我有一些通用代码,我想向它发送一个范围,然后在该范围上创建一个跨度。我试过发送一个vector,没问题。结果iota失败。

template <typename TRange>
requires std::ranges::random_access_range<TRange>
void Foo(TRange const & r)
{
     // The algorithm starts with a full span and then partitions
     auto s = std::span(r.begin(), r.end());
}
Run Code Online (Sandbox Code Playgroud)

该代码是从 boost 移植的,在那里我会使用boost::make_iterator_range() …

c++ c++20 std-span

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