std::span 构造函数
std::span
类可以通过多种不同的方式构造。使用右上角的按钮,方便地使用箭头导航。
std::span
是一个类模板,具有以下类型参数,在构造函数中使用:
公共 | T | 元素的类型。 |
公共 | Extent | 容器中的元素数量,如果为动态则为 |
默认构造函数
- C++20
- 简化
- 详细
span();
- 此构造函数是
constexpr
和noexcept
constexpr span() noexcept;
默认构造函数。构造一个空的 span,其
data() == nullptr
size() == 0
重载决议
此重载仅在以下情况下参与重载解析
extent == 0
或
extent == std::dynamic_extent
复杂度
常数 - O(1)。
示例
#include <iostream>
#include <span>
int main() {
// Default constructed span<int>:
std::span<int> s;
std::cout << "s.size(): " << s.size();
}
s.size(): 0
迭代器 + 大小构造函数
- C++20
template< class It >
explicit(extent != std::dynamic_extent)
constexpr span( It first, size_type count );
构造一个 span,它是范围 [ first, first + count ) 的视图。
结果 span 具有
data() == std::to_address(first)
size() == count
行为未定义
如果- [ first, first + count ) 不是有效范围
It
不符合contiguous_iterator
模型
或extent != std::dynamic_extent
且count != extent
重载决议
此重载仅在以下情况下参与重载解析
It
满足contiguous_iterator
和- 从
std::iter_reference_t<It>
到element_type
的转换最多为限定符转换
复杂度
常数 - O(1)。
示例
#include <iostream>
#include <vector>
#include <span>
int main() {
std::vector<int> v{1, 2, 3, 4, 5};
std::span<int> s(v.cbegin(), 3);
std::cout << "s.size(): " << s.size() << '\n';
std::cout << "elems: ";
for(int num : s) std::cout << num << ' ';
}
s.size(): 3
elems: 1 2 3
基于范围的构造函数(迭代器)
- C++20
template< class It, class End >
explicit(extent != std::dynamic_extent)
constexpr span( It first, End last );
构造一个 span,它是范围 [ first, last ) 的视图。
结果 span 具有
data() == std::to_address(first)
size() == last - first
行为未定义
如果- [ first, first ) 不是有效范围
It
不符合contiguous_iterator
模型End
不符合It
的sized_sentinel_for
模型
或extent != std::dynamic_extent
且last - first != extent
重载决议
此重载仅在以下情况下参与重载解析
It
满足contiguous_iterator
End
满足sized_sentinel_for
- 从
std::iter_reference_t<It>
到element_type
的转换最多为限定符转换
和 std::is_convertible_v<End, std::size_t>
为false
复杂度
常数 - O(1)。
示例
#include <iostream>
#include <vector>
#include <span>
int main() {
std::vector<int> v{1, 2, 3, 4, 5};
std::span<int> s(v.begin() + 1, v.end() - 1);
std::cout << "s.size(): " << s.size() << '\n';
std::cout << "elems: ";
for(int num : s) {
std::cout << num << ' ';
}
}
s.size(): 3
elems: 2 3 4
C 数组和std::array
构造函数
- C++20
// (1)
template< std::size_t N >
constexpr span( std::type_identity_t<element_type> (&arr)[N] ) noexcept;
// (2)
template< class U, std::size_t N >
constexpr span( std::array<U, N>& arr ) noexcept;
// (3)
template< class U, std::size_t N >
constexpr span( const std::array<U, N>& arr ) noexcept;
构造一个 span,它是数组 arr
的视图。
结果 span 具有
size() == N
data() == std::data(arr)
重载决议
这些重载仅在以下情况下参与重载解析
extent == std::dynamic_extent
或N == extent
和- 从
std::remove_pointer_t<decltype(data(arr))>
到element_type
的转换最多为限定符转换
复杂度
常数 - O(1)。
示例
#include <iostream>
#include <array>
#include <span>
template <typename Type, std::size_t Extent>
void present_span(std::span<Type, Extent> s) {
std::cout << "s.size(): " << s.size() << '\n';
std::cout << "elems: ";
for(int num : s) {
std::cout << num << ' ';
}
std::cout << "\n\n";
}
int main() {
int arr[] = {1, 2, 3, 4, 5};
present_span(std::span(arr)); // (1)
std::array<int, 5> arr2 = {6, 7, 8, 9, 10};
present_span(std::span(arr2)); // (2)
const std::array<int, 5> arr3 = {12, 13, 14, 15, 16};
present_span(std::span(arr3)); // (3)
}
s.size(): 5
elems: 1 2 3 4 5
s.size(): 5
elems: 6 7 8 9 10
s.size(): 5
elems: 12 13 14 15 16
任意范围构造函数
- C++20
template< class R >
explicit(extent != std::dynamic_extent)
constexpr span( R&& range );
构造一个 span,它是范围 range
的视图。结果 span 具有
size() == std::ranges::size(range)
data() == std::ranges::data(range)
行为未定义
如果R
不符合contiguous_range
和sized_range
模型
或R
不符合borrowed_range
模型,同时element_type
为非 const
或extent != std::dynamic_extent
且std::ranges::size(range) != extent
重载决议
这些重载仅在以下情况下参与重载解析
R
满足contiguous_range
和sized_range
- 要么
R
满足borrowed_range
,要么std::is_const_v<element_type>
为true
std::remove_cvref_t<R>
不是std::span
的特化std::remove_cvref_t<R>
不是std::array
的特化std::is_array_v<std::remove_cvref_t<R>>
为false
且- 从
std::ranges::range_reference_t<R>
到element_type
的转换最多为限定符转换
复杂度
常数 - O(1)。
示例
#include <iostream>
#include <vector>
#include <span>
template <typename Type, std::size_t Extent>
void present_span(std::span<Type, Extent> s) {
std::cout << "s.size(): " << s.size() << '\n';
std::cout << "elems: ";
for(int num : s) {
std::cout << num << ' ';
}
std::cout << "\n\n";
}
int main() {
std::vector<int> v = {1, 2, 3, 4};
present_span(std::span(v)); // vector is a valid range
struct custom_range {
int* begin() { return arr.data(); }
int* end() { return arr.data() + arr.size(); }
std::vector<int> arr{1, 2, 3};
};
custom_range cr;
present_span(std::span(cr)); // cr is a valid range
}
s.size(): 4
elems: 1 2 3 4
s.size(): 3
elems: 1 2 3
转换构造函数
- C++20
template< class U, std::size_t N >
explicit(extent != std::dynamic_extent && N == std::dynamic_extent)
constexpr span( const std::span<U, N>& source ) noexcept;
从另一个 span 源的转换构造函数。结果 span 具有
size() == source.size()
data() == source.data()
行为未定义
如果extent != dynamic_extent
和source.size() != extent
重载决议
这些重载仅在以下情况下参与重载解析
- 至少以下之一:
extent == std::dynamic_extent
N == std::dynamic_extent
N == extent
为true
和
- 从
U
到element_type
的转换最多为限定符转换
复杂度
常数 - O(1)。
示例
#include <iostream>
#include <vector>
#include <span>
template <typename Type, std::size_t Extent>
void present_span(std::span<Type, Extent> s) {
std::cout << "s.size(): " << s.size() << '\n';
std::cout << "elems: ";
for(int num : s) {
std::cout << num << ' ';
}
std::cout << "\n\n";
}
int main() {
std::vector<int> source = { 1, 2, 3, 4, 5 };
std::array<const int, 4> source2 = { 10, 11, 12, 13 };
std::span<int> s1 = source;
std::span<const int> s2 = source2;
present_span(s1);
present_span(s2);
s2 = s1; // converting ctor
present_span(s1);
present_span(s2);
}
s.size(): 5
elems: 1 2 3 4 5
s.size(): 4
elems: 10 11 12 13
s.size(): 5
elems: 1 2 3 4 5
s.size(): 5
elems: 1 2 3 4 5
默认复制构造函数
- C++20
constexpr span( const span& other ) noexcept = default;
默认复制构造函数复制大小和数据指针。结果 span 具有
size() == other.size()
data() == other.data()
复杂度
常数 - O(1)。
示例
#include <iostream>
#include <vector>
#include <span>
template <typename Type, std::size_t Extent>
void present_span(std::span<Type, Extent> s) {
std::cout << "s.size(): " << s.size() << '\n';
std::cout << "elems: ";
for(int num : s) {
std::cout << num << ' ';
}
std::cout << "\n\n";
}
int main() {
std::vector<int> source = { 1, 2, 3, 4, 5 };
std::vector<int> source2 = { 5, 4, 3, 2, 1 };
std::span<int> s1 = source;
std::span<int> s2 = source2;
present_span(s1);
present_span(s2);
s2 = s1; // copy ctor
present_span(s1);
present_span(s2);
}
s.size(): 5
elems: 1 2 3 4 5
s.size(): 5
elems: 5 4 3 2 1
s.size(): 5
elems: 1 2 3 4 5
s.size(): 5
elems: 1 2 3 4 5