std::vector几乎所有其他容器都有一种非常方便的边界检查方法:at(). std::span显然没有那个。
at()?给定某个函数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) 考虑一个大内存容器。在这个简单的例子中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) 我最好的猜测是,委员会要么忘记了这个用例,要么不想使用概念/要求将类型限制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.
标准容器传播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) 我想这样做
#include <vector>
#include <span>
struct S
{
std::vector<int> v;
void set(std::span<int> _v)
{
v = _v;
}
};
Run Code Online (Sandbox Code Playgroud)
但它不编译。有哪些替代方案?
我有一个const z* zs = nullptr;
我想转换zs 为std::span
当我尝试这样做时,std::span<const z>(zs) 我收到一条错误消息
\n\n错误:没有匹配的函数可调用 \xe2\x80\x98std::span::span(const z* const&)\xe2\x80\x99
\n
如何转换为 zsstd::span
我试过std::span<const z>(zs[0])了,好像可以编译。这种方式正确吗?
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) 标题。
我正在实现这个类:
#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