|
|
Line 1: |
Line 1: |
− | {{cpp/title|span}}
| + | #REDIRECT [[enwiki:Rust_(programming_language)]] |
− | {{cpp/container/span/navbar}}
| + | |
− | {{dcl begin}}
| + | |
− | {{dcl header|span}}
| + | |
− | {{dcl|since=c++20|1=
| + | |
− | template<
| + | |
− | class T,
| + | |
− | std::size_t Extent = std::dynamic_extent
| + | |
− | > class span;
| + | |
− | }}
| + | |
− | {{dcl end}}
| + | |
− | | + | |
− | The class template {{tt|span}} describes an object that can refer to a contiguous sequence of objects with the first element of the sequence at position zero. A {{tt|span}} can either have a ''static'' extent, in which case the number of elements in the sequence is known at compile-time and encoded in the type, or a ''dynamic'' extent.
| + | |
− | | + | |
− | If a {{tt|span}} has ''dynamic'' extent, a typical implementation holds two members: a pointer to {{tt|T}} and a size.
| + | |
− | A {{tt|span}} with ''static'' extent may have only one member: a pointer to {{tt|T}}.
| + | |
− | | + | |
− | {{rrev|since=c++23|
| + | |
− | Every specialization of {{tt|std::span}} is a {{named req|TriviallyCopyable}} type.
| + | |
− | }}
| + | |
− | | + | |
− | ===Template parameters===
| + | |
− | {{par begin}}
| + | |
− | {{par|T|element type; must be a complete object type that is not an abstract class type}}
| + | |
− | {{par|Extent|the number of elements in the sequence, or {{tt|std::dynamic_extent}} if dynamic}}
| + | |
− | {{par end}}
| + | |
− | | + | |
− | ===Member types===
| + | |
− | {{dsc begin}}
| + | |
− | {{dsc hitem|Member type|Definition}}
| + | |
− | {{dsc|{{tt|element_type}}|{{tt|T}}}}
| + | |
− | {{dsc|{{tt|value_type}}|{{co|std::remove_cv_t<T>}}}}
| + | |
− | {{dsc|{{tt|size_type}}|{{lc|std::size_t}}}}
| + | |
− | {{dsc|{{tt|difference_type}}|{{lc|std::ptrdiff_t}}}}
| + | |
− | {{dsc|{{tt|pointer}}|{{co|T*}}}}
| + | |
− | {{dsc|{{tt|const_pointer}}|{{co|const T*}}}}
| + | |
− | {{dsc|{{tt|reference}}|{{co|T&}}}}
| + | |
− | {{dsc|{{tt|const_reference}}|{{co|const T&}}}}
| + | |
− | {{dsc|{{tt|iterator}}|implementation-defined {{named req|RandomAccessIterator}}, {{named req|ConstexprIterator}}, and {{lconcept|contiguous_iterator}} whose {{tt|value_type}} is {{tt|value_type}}}}
| + | |
− | {{dsc|{{tt|reverse_iterator}}|{{co|std::reverse_iterator<iterator>}}}}
| + | |
− | {{dsc end}}
| + | |
− | | + | |
− | {{petty|Note: {{tt|iterator}} is a mutable iterator if {{tt|T}} is not const-qualified.}}
| + | |
− | | + | |
− | All requirements on the iterator types of a {{named req|Container}} apply to the {{tt|iterator}} type of {{tt|span}} as well.
| + | |
− | | + | |
− | ===Member constant===
| + | |
− | {{ddcl|since=c++20|1=
| + | |
− | static constexpr std::size_t extent = Extent;
| + | |
− | }}
| + | |
− | | + | |
− | ===Member functions===
| + | |
− | {{dsc begin}}
| + | |
− | {{dsc inc|cpp/container/span/dsc constructor}}
| + | |
− | {{dsc inc|cpp/container/span/dsc operator{{=}}}}
| + | |
− | | + | |
− | {{dsc h2|Iterators}}
| + | |
− | {{dsc inc|cpp/container/dsc begin|span}}
| + | |
− | {{dsc inc|cpp/container/dsc end|span}}
| + | |
− | {{dsc inc|cpp/container/dsc rbegin|span}}
| + | |
− | {{dsc inc|cpp/container/dsc rend|span}}
| + | |
− | | + | |
− | {{dsc h2|Element access}}
| + | |
− | {{dsc inc|cpp/container/dsc front|span}}
| + | |
− | {{dsc inc|cpp/container/dsc back|span}}
| + | |
− | {{dsc inc|cpp/container/span/dsc operator_at}}
| + | |
− | {{dsc inc|cpp/container/span/dsc data}}
| + | |
− | | + | |
− | {{dsc h2|Observers}}
| + | |
− | {{dsc inc|cpp/container/span/dsc size}}
| + | |
− | {{dsc inc|cpp/container/span/dsc size_bytes}}
| + | |
− | {{dsc inc|cpp/container/span/dsc empty}}
| + | |
− | | + | |
− | {{dsc h2|Subviews}}
| + | |
− | {{dsc inc|cpp/container/span/dsc first}}
| + | |
− | {{dsc inc|cpp/container/span/dsc last}}
| + | |
− | {{dsc inc|cpp/container/span/dsc subspan}}
| + | |
− | {{dsc end}}
| + | |
− | | + | |
− | ===Non-member functions===
| + | |
− | {{dsc begin}}
| + | |
− | {{dsc inc|cpp/container/span/dsc as_bytes}}
| + | |
− | {{dsc end}}
| + | |
− | | + | |
− | ===Non-member constant===
| + | |
− | {{dsc begin}}
| + | |
− | {{dsc inc|cpp/container/span/dsc dynamic_extent}}
| + | |
− | {{dsc end}}
| + | |
− | | + | |
− | ===Helper templates===
| + | |
− | {{ddcl|since=c++20|num=1|1=
| + | |
− | template< class T, std::size_t Extent >
| + | |
− | inline constexpr bool ranges::enable_borrowed_range<std::span<T, Extent>> = true;
| + | |
− | }}
| + | |
− | This specialization of {{lc|ranges::enable_borrowed_range}} makes {{tt|span}} satisfy {{lconcept|borrowed_range}}.
| + | |
− | | + | |
− | {{ddcl|since=c++20|1=
| + | |
− | template< class T, std::size_t Extent >
| + | |
− | inline constexpr bool ranges::enable_view<std::span<T, Extent>> = true;
| + | |
− | }}
| + | |
− | This specialization of {{lc|ranges::enable_view}} makes {{tt|span}} satisfy {{lconcept|view}}.
| + | |
− | | + | |
− | ==={{rl|deduction guides|Deduction guides}}{{mark c++20}}===
| + | |
− | | + | |
− | ===Notes===
| + | |
− | Specializations of {{tt|std::span}} are already trivially copyable types in all existing implementations, even before the formal requirement introduced in C++23.
| + | |
− | | + | |
− | {{feature test macro|__cpp_lib_span|std=C++20|value=202002L|[[#Top|{{tt|std::span}}]]}}
| + | |
− | | + | |
− | ===Example===
| + | |
− | {{example
| + | |
− | |The example uses {{tt|std::span}} to implement some algorithms on contiguous ranges.
| + | |
− | |code=
| + | |
− | #include <algorithm>
| + | |
− | #include <cstddef>
| + | |
− | #include <iostream>
| + | |
− | #include <span>
| + | |
− | | + | |
− | template<class T, std::size_t N>
| + | |
− | [[nodiscard]] | + | |
− | constexpr auto slide(std::span<T,N> s, std::size_t offset, std::size_t width)
| + | |
− | {
| + | |
− | return s.subspan(offset, offset + width <= s.size() ? width : 0U);
| + | |
− | }
| + | |
− | | + | |
− | template<class T, std::size_t N, std::size_t M>
| + | |
− | constexpr bool starts_with(std::span<T,N> data, std::span<T,M> prefix)
| + | |
− | {
| + | |
− | return data.size() >= prefix.size()
| + | |
− | && std::equal(prefix.begin(), prefix.end(), data.begin());
| + | |
− | }
| + | |
− | | + | |
− | template<class T, std::size_t N, std::size_t M>
| + | |
− | constexpr bool ends_with(std::span<T,N> data, std::span<T,M> suffix)
| + | |
− | {
| + | |
− | return data.size() >= suffix.size()
| + | |
− | && std::equal(data.end() - suffix.size(), data.end(),
| + | |
− | suffix.end() - suffix.size());
| + | |
− | }
| + | |
− | | + | |
− | template<class T, std::size_t N, std::size_t M>
| + | |
− | constexpr bool contains(std::span<T,N> span, std::span<T,M> sub)
| + | |
− | {
| + | |
− | return std::search(span.begin(), span.end(), sub.begin(), sub.end()) != span.end();
| + | |
− | // return std::ranges::search(span, sub).begin() != span.end();
| + | |
− | }
| + | |
− | | + | |
− | void print(const auto& seq)
| + | |
− | {
| + | |
− | for (const auto& elem : seq)
| + | |
− | std::cout << elem << ' ';
| + | |
− | std::cout << '\n';
| + | |
− | }
| + | |
− | | + | |
− | int main()
| + | |
− | {
| + | |
− | constexpr int a[] {0, 1, 2, 3, 4, 5, 6, 7, 8};
| + | |
− | constexpr int b[] {8, 7, 6};
| + | |
− | | + | |
− | for (std::size_t offset{}; ; ++offset)
| + | |
− | {
| + | |
− | static constexpr std::size_t width{6};
| + | |
− | auto s = slide(std::span{a}, offset, width);
| + | |
− | if (s.empty())
| + | |
− | break;
| + | |
− | print(s);
| + | |
− | }
| + | |
− | | + | |
− | static_assert(
| + | |
− | starts_with(std::span{a}, std::span{a, 4}) and
| + | |
− | starts_with(std::span{a + 1, 4}, std::span{a + 1, 3}) and
| + | |
− | ! starts_with(std::span{a}, std::span{b}) and
| + | |
− | ! starts_with(std::span{a, 8}, std::span{a + 1, 3}) and
| + | |
− | ends_with(std::span{a}, std::span{a + 6, 3}) and
| + | |
− | ! ends_with(std::span{a}, std::span{a + 6, 2}) and
| + | |
− | contains(std::span{a}, std::span{a + 1, 4}) and
| + | |
− | ! contains(std::span{a, 8}, std::span{a, 9})
| + | |
− | );
| + | |
− | }
| + | |
− | |output=
| + | |
− | 0 1 2 3 4 5
| + | |
− | 1 2 3 4 5 6
| + | |
− | 2 3 4 5 6 7
| + | |
− | 3 4 5 6 7 8
| + | |
− | }}
| + | |
− | | + | |
− | ===Defect reports===
| + | |
− | {{dr list begin}}
| + | |
− | {{dr list item|paper=P2325R3|std=C++20|before={{tt|span}} of non-zero static extents were not {{tt|view}}|after=they are as {{lconcept|default_initializable}} is not required}}
| + | |
− | {{dr list end}}
| + | |
− | | + | |
− | ===See also===
| + | |
− | {{dsc begin}}
| + | |
− | {{dsc inc|cpp/utility/dsc initializer_list}}
| + | |
− | {{dsc inc|cpp/string/dsc basic_string_view}}
| + | |
− | {{dsc inc|cpp/container/dsc mdspan}}
| + | |
− | {{dsc inc|cpp/ranges/dsc subrange}}
| + | |
− | {{dsc end}}
| + | |
− | | + | |
− | {{langlinks|de|es|ja|ru|zh}}
| + | |