为什么我不能从迭代器构造一个 std::span?
why can't I construct an std::span from iterators?
考虑一个大内存容器。在这个简单的例子中 std::vector<int>
:
std::vector v = { 0, 1, 2, 3, 4, 5 };
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 });
}
输出:
[0, 1, 2, 3, 4, 5]
现在我想制作子集(这就是 std::span
实际上用作视图的地方)。我可以使用迭代器来指定我的范围并从 std::span
调用 this constructor(3)
template< class It, class End >
explicit(extent != std::dynamic_extent)
constexpr span( It first, End last );
但这不起作用:
print(std::span{ v.begin() + 2, v.end() }); //error E0289
C++ no instance of constructor matches the argument list argument types are: (std::_Vector_iterator<std::_Vector_val<std::conditional_t<true, std::_Simple_types, std::_Vec_iter_types<int, size_t, ptrdiff_t, int *, const int *, int &, const int &>>>>, std::_Vector_iterator<std::_Vector_val<std::conditional_t<true, std::_Simple_types, std::_Vec_iter_types<int, size_t, ptrdiff_t, int *, const int *, int &, const int &>>>>)
可以使用带有指针和大小的构造函数(2):
print(std::span{ v.data() + 1, 3 }); //-> prints [1, 2, 3]
但这违背了迭代器的目的。
如何使用迭代器构建 std::span
?我错过了什么吗?
完整代码:
#include <iostream>
#include <vector>
#include <span>
#include <algorithm>
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.begin() + 2, v.end() });
}
在 MSVC 实现构造函数之前,我将使用此 make_span
函数:
template<typename It>
constexpr auto make_span(It begin, It end) {
return std::span<std::remove_pointer_t<It::pointer>>(&(*begin), std::distance(begin, end));
}
使用 Visual Studio Community 2019 版本 16.7.5。配置:x64,发布。 C++ 语言标准 = /std:c++latest
您可以使用迭代器构造一个 span
,它有 such a constructor (as added by P1394, which you can see in [views.span]):
template< class It, class End >
explicit(extent != std::dynamic_extent)
constexpr span( It first, End last );
只是MSVC的标准库没有实现。正如预期的那样,该程序在 gcc 上编译良好。
考虑一个大内存容器。在这个简单的例子中 std::vector<int>
:
std::vector v = { 0, 1, 2, 3, 4, 5 };
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 });
}
输出:
[0, 1, 2, 3, 4, 5]
现在我想制作子集(这就是 std::span
实际上用作视图的地方)。我可以使用迭代器来指定我的范围并从 std::span
template< class It, class End >
explicit(extent != std::dynamic_extent)
constexpr span( It first, End last );
但这不起作用:
print(std::span{ v.begin() + 2, v.end() }); //error E0289
C++ no instance of constructor matches the argument list argument types are: (std::_Vector_iterator<std::_Vector_val<std::conditional_t<true, std::_Simple_types, std::_Vec_iter_types<int, size_t, ptrdiff_t, int *, const int *, int &, const int &>>>>, std::_Vector_iterator<std::_Vector_val<std::conditional_t<true, std::_Simple_types, std::_Vec_iter_types<int, size_t, ptrdiff_t, int *, const int *, int &, const int &>>>>)
可以使用带有指针和大小的构造函数(2):
print(std::span{ v.data() + 1, 3 }); //-> prints [1, 2, 3]
但这违背了迭代器的目的。
如何使用迭代器构建 std::span
?我错过了什么吗?
完整代码:
#include <iostream>
#include <vector>
#include <span>
#include <algorithm>
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.begin() + 2, v.end() });
}
在 MSVC 实现构造函数之前,我将使用此 make_span
函数:
template<typename It>
constexpr auto make_span(It begin, It end) {
return std::span<std::remove_pointer_t<It::pointer>>(&(*begin), std::distance(begin, end));
}
使用 Visual Studio Community 2019 版本 16.7.5。配置:x64,发布。 C++ 语言标准 = /std:c++latest
您可以使用迭代器构造一个 span
,它有 such a constructor (as added by P1394, which you can see in [views.span]):
template< class It, class End >
explicit(extent != std::dynamic_extent)
constexpr span( It first, End last );
只是MSVC的标准库没有实现。正如预期的那样,该程序在 gcc 上编译良好。