xref: /aosp_15_r20/external/libchrome/base/containers/span.h (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright 2017 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker #ifndef BASE_CONTAINERS_SPAN_H_
6*635a8641SAndroid Build Coastguard Worker #define BASE_CONTAINERS_SPAN_H_
7*635a8641SAndroid Build Coastguard Worker 
8*635a8641SAndroid Build Coastguard Worker #include <stddef.h>
9*635a8641SAndroid Build Coastguard Worker 
10*635a8641SAndroid Build Coastguard Worker #include <algorithm>
11*635a8641SAndroid Build Coastguard Worker #include <array>
12*635a8641SAndroid Build Coastguard Worker #include <iterator>
13*635a8641SAndroid Build Coastguard Worker #include <type_traits>
14*635a8641SAndroid Build Coastguard Worker #include <utility>
15*635a8641SAndroid Build Coastguard Worker 
16*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
17*635a8641SAndroid Build Coastguard Worker #include "base/stl_util.h"
18*635a8641SAndroid Build Coastguard Worker 
19*635a8641SAndroid Build Coastguard Worker namespace base {
20*635a8641SAndroid Build Coastguard Worker 
21*635a8641SAndroid Build Coastguard Worker // [views.constants]
22*635a8641SAndroid Build Coastguard Worker constexpr size_t dynamic_extent = static_cast<size_t>(-1);
23*635a8641SAndroid Build Coastguard Worker 
24*635a8641SAndroid Build Coastguard Worker template <typename T, size_t Extent = dynamic_extent>
25*635a8641SAndroid Build Coastguard Worker class span;
26*635a8641SAndroid Build Coastguard Worker 
27*635a8641SAndroid Build Coastguard Worker namespace internal {
28*635a8641SAndroid Build Coastguard Worker 
29*635a8641SAndroid Build Coastguard Worker template <typename T>
30*635a8641SAndroid Build Coastguard Worker struct IsSpanImpl : std::false_type {};
31*635a8641SAndroid Build Coastguard Worker 
32*635a8641SAndroid Build Coastguard Worker template <typename T, size_t Extent>
33*635a8641SAndroid Build Coastguard Worker struct IsSpanImpl<span<T, Extent>> : std::true_type {};
34*635a8641SAndroid Build Coastguard Worker 
35*635a8641SAndroid Build Coastguard Worker template <typename T>
36*635a8641SAndroid Build Coastguard Worker using IsSpan = IsSpanImpl<std::decay_t<T>>;
37*635a8641SAndroid Build Coastguard Worker 
38*635a8641SAndroid Build Coastguard Worker template <typename T>
39*635a8641SAndroid Build Coastguard Worker struct IsStdArrayImpl : std::false_type {};
40*635a8641SAndroid Build Coastguard Worker 
41*635a8641SAndroid Build Coastguard Worker template <typename T, size_t N>
42*635a8641SAndroid Build Coastguard Worker struct IsStdArrayImpl<std::array<T, N>> : std::true_type {};
43*635a8641SAndroid Build Coastguard Worker 
44*635a8641SAndroid Build Coastguard Worker template <typename T>
45*635a8641SAndroid Build Coastguard Worker using IsStdArray = IsStdArrayImpl<std::decay_t<T>>;
46*635a8641SAndroid Build Coastguard Worker 
47*635a8641SAndroid Build Coastguard Worker template <typename T>
48*635a8641SAndroid Build Coastguard Worker using IsCArray = std::is_array<std::remove_reference_t<T>>;
49*635a8641SAndroid Build Coastguard Worker 
50*635a8641SAndroid Build Coastguard Worker template <typename From, typename To>
51*635a8641SAndroid Build Coastguard Worker using IsLegalDataConversion = std::is_convertible<From (*)[], To (*)[]>;
52*635a8641SAndroid Build Coastguard Worker 
53*635a8641SAndroid Build Coastguard Worker template <typename Container, typename T>
54*635a8641SAndroid Build Coastguard Worker using ContainerHasConvertibleData = IsLegalDataConversion<
55*635a8641SAndroid Build Coastguard Worker     std::remove_pointer_t<decltype(base::data(std::declval<Container>()))>,
56*635a8641SAndroid Build Coastguard Worker     T>;
57*635a8641SAndroid Build Coastguard Worker 
58*635a8641SAndroid Build Coastguard Worker template <typename Container>
59*635a8641SAndroid Build Coastguard Worker using ContainerHasIntegralSize =
60*635a8641SAndroid Build Coastguard Worker     std::is_integral<decltype(base::size(std::declval<Container>()))>;
61*635a8641SAndroid Build Coastguard Worker 
62*635a8641SAndroid Build Coastguard Worker template <typename From, size_t FromExtent, typename To, size_t ToExtent>
63*635a8641SAndroid Build Coastguard Worker using EnableIfLegalSpanConversion =
64*635a8641SAndroid Build Coastguard Worker     std::enable_if_t<(ToExtent == dynamic_extent || ToExtent == FromExtent) &&
65*635a8641SAndroid Build Coastguard Worker                      IsLegalDataConversion<From, To>::value>;
66*635a8641SAndroid Build Coastguard Worker 
67*635a8641SAndroid Build Coastguard Worker // SFINAE check if Array can be converted to a span<T>.
68*635a8641SAndroid Build Coastguard Worker template <typename Array, size_t N, typename T, size_t Extent>
69*635a8641SAndroid Build Coastguard Worker using EnableIfSpanCompatibleArray =
70*635a8641SAndroid Build Coastguard Worker     std::enable_if_t<(Extent == dynamic_extent || Extent == N) &&
71*635a8641SAndroid Build Coastguard Worker                      ContainerHasConvertibleData<Array, T>::value>;
72*635a8641SAndroid Build Coastguard Worker 
73*635a8641SAndroid Build Coastguard Worker // SFINAE check if Container can be converted to a span<T>.
74*635a8641SAndroid Build Coastguard Worker template <typename Container, typename T>
75*635a8641SAndroid Build Coastguard Worker using EnableIfSpanCompatibleContainer =
76*635a8641SAndroid Build Coastguard Worker     std::enable_if_t<!internal::IsSpan<Container>::value &&
77*635a8641SAndroid Build Coastguard Worker                      !internal::IsStdArray<Container>::value &&
78*635a8641SAndroid Build Coastguard Worker                      !internal::IsCArray<Container>::value &&
79*635a8641SAndroid Build Coastguard Worker                      ContainerHasConvertibleData<Container, T>::value &&
80*635a8641SAndroid Build Coastguard Worker                      ContainerHasIntegralSize<Container>::value>;
81*635a8641SAndroid Build Coastguard Worker 
82*635a8641SAndroid Build Coastguard Worker }  // namespace internal
83*635a8641SAndroid Build Coastguard Worker 
84*635a8641SAndroid Build Coastguard Worker // A span is a value type that represents an array of elements of type T. Since
85*635a8641SAndroid Build Coastguard Worker // it only consists of a pointer to memory with an associated size, it is very
86*635a8641SAndroid Build Coastguard Worker // light-weight. It is cheap to construct, copy, move and use spans, so that
87*635a8641SAndroid Build Coastguard Worker // users are encouraged to use it as a pass-by-value parameter. A span does not
88*635a8641SAndroid Build Coastguard Worker // own the underlying memory, so care must be taken to ensure that a span does
89*635a8641SAndroid Build Coastguard Worker // not outlive the backing store.
90*635a8641SAndroid Build Coastguard Worker //
91*635a8641SAndroid Build Coastguard Worker // span is somewhat analogous to StringPiece, but with arbitrary element types,
92*635a8641SAndroid Build Coastguard Worker // allowing mutation if T is non-const.
93*635a8641SAndroid Build Coastguard Worker //
94*635a8641SAndroid Build Coastguard Worker // span is implicitly convertible from C++ arrays, as well as most [1]
95*635a8641SAndroid Build Coastguard Worker // container-like types that provide a data() and size() method (such as
96*635a8641SAndroid Build Coastguard Worker // std::vector<T>). A mutable span<T> can also be implicitly converted to an
97*635a8641SAndroid Build Coastguard Worker // immutable span<const T>.
98*635a8641SAndroid Build Coastguard Worker //
99*635a8641SAndroid Build Coastguard Worker // Consider using a span for functions that take a data pointer and size
100*635a8641SAndroid Build Coastguard Worker // parameter: it allows the function to still act on an array-like type, while
101*635a8641SAndroid Build Coastguard Worker // allowing the caller code to be a bit more concise.
102*635a8641SAndroid Build Coastguard Worker //
103*635a8641SAndroid Build Coastguard Worker // For read-only data access pass a span<const T>: the caller can supply either
104*635a8641SAndroid Build Coastguard Worker // a span<const T> or a span<T>, while the callee will have a read-only view.
105*635a8641SAndroid Build Coastguard Worker // For read-write access a mutable span<T> is required.
106*635a8641SAndroid Build Coastguard Worker //
107*635a8641SAndroid Build Coastguard Worker // Without span:
108*635a8641SAndroid Build Coastguard Worker //   Read-Only:
109*635a8641SAndroid Build Coastguard Worker //     // std::string HexEncode(const uint8_t* data, size_t size);
110*635a8641SAndroid Build Coastguard Worker //     std::vector<uint8_t> data_buffer = GenerateData();
111*635a8641SAndroid Build Coastguard Worker //     std::string r = HexEncode(data_buffer.data(), data_buffer.size());
112*635a8641SAndroid Build Coastguard Worker //
113*635a8641SAndroid Build Coastguard Worker //  Mutable:
114*635a8641SAndroid Build Coastguard Worker //     // ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt, Args...);
115*635a8641SAndroid Build Coastguard Worker //     char str_buffer[100];
116*635a8641SAndroid Build Coastguard Worker //     SafeSNPrintf(str_buffer, sizeof(str_buffer), "Pi ~= %lf", 3.14);
117*635a8641SAndroid Build Coastguard Worker //
118*635a8641SAndroid Build Coastguard Worker // With span:
119*635a8641SAndroid Build Coastguard Worker //   Read-Only:
120*635a8641SAndroid Build Coastguard Worker //     // std::string HexEncode(base::span<const uint8_t> data);
121*635a8641SAndroid Build Coastguard Worker //     std::vector<uint8_t> data_buffer = GenerateData();
122*635a8641SAndroid Build Coastguard Worker //     std::string r = HexEncode(data_buffer);
123*635a8641SAndroid Build Coastguard Worker //
124*635a8641SAndroid Build Coastguard Worker //  Mutable:
125*635a8641SAndroid Build Coastguard Worker //     // ssize_t SafeSNPrintf(base::span<char>, const char* fmt, Args...);
126*635a8641SAndroid Build Coastguard Worker //     char str_buffer[100];
127*635a8641SAndroid Build Coastguard Worker //     SafeSNPrintf(str_buffer, "Pi ~= %lf", 3.14);
128*635a8641SAndroid Build Coastguard Worker //
129*635a8641SAndroid Build Coastguard Worker // Spans with "const" and pointers
130*635a8641SAndroid Build Coastguard Worker // -------------------------------
131*635a8641SAndroid Build Coastguard Worker //
132*635a8641SAndroid Build Coastguard Worker // Const and pointers can get confusing. Here are vectors of pointers and their
133*635a8641SAndroid Build Coastguard Worker // corresponding spans:
134*635a8641SAndroid Build Coastguard Worker //
135*635a8641SAndroid Build Coastguard Worker //   const std::vector<int*>        =>  base::span<int* const>
136*635a8641SAndroid Build Coastguard Worker //   std::vector<const int*>        =>  base::span<const int*>
137*635a8641SAndroid Build Coastguard Worker //   const std::vector<const int*>  =>  base::span<const int* const>
138*635a8641SAndroid Build Coastguard Worker //
139*635a8641SAndroid Build Coastguard Worker // Differences from the working group proposal
140*635a8641SAndroid Build Coastguard Worker // -------------------------------------------
141*635a8641SAndroid Build Coastguard Worker //
142*635a8641SAndroid Build Coastguard Worker // https://wg21.link/P0122 is the latest working group proposal, Chromium
143*635a8641SAndroid Build Coastguard Worker // currently implements R7. Differences between the proposal and the
144*635a8641SAndroid Build Coastguard Worker // implementation are documented in subsections below.
145*635a8641SAndroid Build Coastguard Worker //
146*635a8641SAndroid Build Coastguard Worker // Differences from [span.objectrep]:
147*635a8641SAndroid Build Coastguard Worker // - as_bytes() and as_writable_bytes() return spans of uint8_t instead of
148*635a8641SAndroid Build Coastguard Worker //   std::byte
149*635a8641SAndroid Build Coastguard Worker //
150*635a8641SAndroid Build Coastguard Worker // Differences in constants and types:
151*635a8641SAndroid Build Coastguard Worker // - index_type is aliased to size_t
152*635a8641SAndroid Build Coastguard Worker //
153*635a8641SAndroid Build Coastguard Worker // Differences from [span.sub]:
154*635a8641SAndroid Build Coastguard Worker // - using size_t instead of ptrdiff_t for indexing
155*635a8641SAndroid Build Coastguard Worker //
156*635a8641SAndroid Build Coastguard Worker // Differences from [span.obs]:
157*635a8641SAndroid Build Coastguard Worker // - using size_t instead of ptrdiff_t to represent size()
158*635a8641SAndroid Build Coastguard Worker //
159*635a8641SAndroid Build Coastguard Worker // Differences from [span.elem]:
160*635a8641SAndroid Build Coastguard Worker // - using size_t instead of ptrdiff_t for indexing
161*635a8641SAndroid Build Coastguard Worker //
162*635a8641SAndroid Build Coastguard Worker // Furthermore, all constructors and methods are marked noexcept due to the lack
163*635a8641SAndroid Build Coastguard Worker // of exceptions in Chromium.
164*635a8641SAndroid Build Coastguard Worker //
165*635a8641SAndroid Build Coastguard Worker // Due to the lack of class template argument deduction guides in C++14
166*635a8641SAndroid Build Coastguard Worker // appropriate make_span() utility functions are provided.
167*635a8641SAndroid Build Coastguard Worker 
168*635a8641SAndroid Build Coastguard Worker // [span], class template span
169*635a8641SAndroid Build Coastguard Worker template <typename T, size_t Extent>
170*635a8641SAndroid Build Coastguard Worker class span {
171*635a8641SAndroid Build Coastguard Worker  public:
172*635a8641SAndroid Build Coastguard Worker   using element_type = T;
173*635a8641SAndroid Build Coastguard Worker   using value_type = std::remove_cv_t<T>;
174*635a8641SAndroid Build Coastguard Worker   using index_type = size_t;
175*635a8641SAndroid Build Coastguard Worker   using difference_type = ptrdiff_t;
176*635a8641SAndroid Build Coastguard Worker   using pointer = T*;
177*635a8641SAndroid Build Coastguard Worker   using reference = T&;
178*635a8641SAndroid Build Coastguard Worker   using iterator = T*;
179*635a8641SAndroid Build Coastguard Worker   using const_iterator = const T*;
180*635a8641SAndroid Build Coastguard Worker   using reverse_iterator = std::reverse_iterator<iterator>;
181*635a8641SAndroid Build Coastguard Worker   using const_reverse_iterator = std::reverse_iterator<const_iterator>;
182*635a8641SAndroid Build Coastguard Worker   static constexpr index_type extent = Extent;
183*635a8641SAndroid Build Coastguard Worker 
184*635a8641SAndroid Build Coastguard Worker   // [span.cons], span constructors, copy, assignment, and destructor
185*635a8641SAndroid Build Coastguard Worker   constexpr span() noexcept : data_(nullptr), size_(0) {
186*635a8641SAndroid Build Coastguard Worker     static_assert(Extent == dynamic_extent || Extent == 0, "Invalid Extent");
187*635a8641SAndroid Build Coastguard Worker   }
188*635a8641SAndroid Build Coastguard Worker 
189*635a8641SAndroid Build Coastguard Worker   constexpr span(T* data, size_t size) noexcept : data_(data), size_(size) {
190*635a8641SAndroid Build Coastguard Worker     CHECK(Extent == dynamic_extent || Extent == size);
191*635a8641SAndroid Build Coastguard Worker   }
192*635a8641SAndroid Build Coastguard Worker 
193*635a8641SAndroid Build Coastguard Worker   // Artificially templatized to break ambiguity for span(ptr, 0).
194*635a8641SAndroid Build Coastguard Worker   template <typename = void>
195*635a8641SAndroid Build Coastguard Worker   constexpr span(T* begin, T* end) noexcept : span(begin, end - begin) {
196*635a8641SAndroid Build Coastguard Worker     // Note: CHECK_LE is not constexpr, hence regular CHECK must be used.
197*635a8641SAndroid Build Coastguard Worker     CHECK(begin <= end);
198*635a8641SAndroid Build Coastguard Worker   }
199*635a8641SAndroid Build Coastguard Worker 
200*635a8641SAndroid Build Coastguard Worker   template <
201*635a8641SAndroid Build Coastguard Worker       size_t N,
202*635a8641SAndroid Build Coastguard Worker       typename = internal::EnableIfSpanCompatibleArray<T (&)[N], N, T, Extent>>
203*635a8641SAndroid Build Coastguard Worker   constexpr span(T (&array)[N]) noexcept : span(base::data(array), N) {}
204*635a8641SAndroid Build Coastguard Worker 
205*635a8641SAndroid Build Coastguard Worker   template <
206*635a8641SAndroid Build Coastguard Worker       size_t N,
207*635a8641SAndroid Build Coastguard Worker       typename = internal::
208*635a8641SAndroid Build Coastguard Worker           EnableIfSpanCompatibleArray<std::array<value_type, N>&, N, T, Extent>>
209*635a8641SAndroid Build Coastguard Worker   constexpr span(std::array<value_type, N>& array) noexcept
210*635a8641SAndroid Build Coastguard Worker       : span(base::data(array), N) {}
211*635a8641SAndroid Build Coastguard Worker 
212*635a8641SAndroid Build Coastguard Worker   template <size_t N,
213*635a8641SAndroid Build Coastguard Worker             typename = internal::EnableIfSpanCompatibleArray<
214*635a8641SAndroid Build Coastguard Worker                 const std::array<value_type, N>&,
215*635a8641SAndroid Build Coastguard Worker                 N,
216*635a8641SAndroid Build Coastguard Worker                 T,
217*635a8641SAndroid Build Coastguard Worker                 Extent>>
218*635a8641SAndroid Build Coastguard Worker   constexpr span(const std::array<value_type, N>& array) noexcept
219*635a8641SAndroid Build Coastguard Worker       : span(base::data(array), N) {}
220*635a8641SAndroid Build Coastguard Worker 
221*635a8641SAndroid Build Coastguard Worker   // Conversion from a container that has compatible base::data() and integral
222*635a8641SAndroid Build Coastguard Worker   // base::size().
223*635a8641SAndroid Build Coastguard Worker   template <typename Container,
224*635a8641SAndroid Build Coastguard Worker             typename = internal::EnableIfSpanCompatibleContainer<Container&, T>>
225*635a8641SAndroid Build Coastguard Worker   constexpr span(Container& container) noexcept
226*635a8641SAndroid Build Coastguard Worker       : span(base::data(container), base::size(container)) {}
227*635a8641SAndroid Build Coastguard Worker 
228*635a8641SAndroid Build Coastguard Worker   template <
229*635a8641SAndroid Build Coastguard Worker       typename Container,
230*635a8641SAndroid Build Coastguard Worker       typename = internal::EnableIfSpanCompatibleContainer<const Container&, T>>
231*635a8641SAndroid Build Coastguard Worker   span(const Container& container) noexcept
232*635a8641SAndroid Build Coastguard Worker       : span(base::data(container), base::size(container)) {}
233*635a8641SAndroid Build Coastguard Worker 
234*635a8641SAndroid Build Coastguard Worker   constexpr span(const span& other) noexcept = default;
235*635a8641SAndroid Build Coastguard Worker 
236*635a8641SAndroid Build Coastguard Worker   // Conversions from spans of compatible types and extents: this allows a
237*635a8641SAndroid Build Coastguard Worker   // span<T> to be seamlessly used as a span<const T>, but not the other way
238*635a8641SAndroid Build Coastguard Worker   // around. If extent is not dynamic, OtherExtent has to be equal to Extent.
239*635a8641SAndroid Build Coastguard Worker   template <
240*635a8641SAndroid Build Coastguard Worker       typename U,
241*635a8641SAndroid Build Coastguard Worker       size_t OtherExtent,
242*635a8641SAndroid Build Coastguard Worker       typename =
243*635a8641SAndroid Build Coastguard Worker           internal::EnableIfLegalSpanConversion<U, OtherExtent, T, Extent>>
244*635a8641SAndroid Build Coastguard Worker   constexpr span(const span<U, OtherExtent>& other)
245*635a8641SAndroid Build Coastguard Worker       : span(other.data(), other.size()) {}
246*635a8641SAndroid Build Coastguard Worker 
247*635a8641SAndroid Build Coastguard Worker   constexpr span& operator=(const span& other) noexcept = default;
248*635a8641SAndroid Build Coastguard Worker   ~span() noexcept = default;
249*635a8641SAndroid Build Coastguard Worker 
250*635a8641SAndroid Build Coastguard Worker   // [span.sub], span subviews
251*635a8641SAndroid Build Coastguard Worker   template <size_t Count>
252*635a8641SAndroid Build Coastguard Worker   constexpr span<T, Count> first() const noexcept {
253*635a8641SAndroid Build Coastguard Worker     static_assert(Extent == dynamic_extent || Count <= Extent,
254*635a8641SAndroid Build Coastguard Worker                   "Count must not exceed Extent");
255*635a8641SAndroid Build Coastguard Worker     CHECK(Extent != dynamic_extent || Count <= size());
256*635a8641SAndroid Build Coastguard Worker     return {data(), Count};
257*635a8641SAndroid Build Coastguard Worker   }
258*635a8641SAndroid Build Coastguard Worker 
259*635a8641SAndroid Build Coastguard Worker   template <size_t Count>
260*635a8641SAndroid Build Coastguard Worker   constexpr span<T, Count> last() const noexcept {
261*635a8641SAndroid Build Coastguard Worker     static_assert(Extent == dynamic_extent || Count <= Extent,
262*635a8641SAndroid Build Coastguard Worker                   "Count must not exceed Extent");
263*635a8641SAndroid Build Coastguard Worker     CHECK(Extent != dynamic_extent || Count <= size());
264*635a8641SAndroid Build Coastguard Worker     return {data() + (size() - Count), Count};
265*635a8641SAndroid Build Coastguard Worker   }
266*635a8641SAndroid Build Coastguard Worker 
267*635a8641SAndroid Build Coastguard Worker   template <size_t Offset, size_t Count = dynamic_extent>
268*635a8641SAndroid Build Coastguard Worker   constexpr span<T,
269*635a8641SAndroid Build Coastguard Worker                  (Count != dynamic_extent
270*635a8641SAndroid Build Coastguard Worker                      ? Count
271*635a8641SAndroid Build Coastguard Worker                      : (Extent != dynamic_extent ? Extent - Offset
272*635a8641SAndroid Build Coastguard Worker                                                  : dynamic_extent))>
273*635a8641SAndroid Build Coastguard Worker   subspan() const noexcept {
274*635a8641SAndroid Build Coastguard Worker     static_assert(Extent == dynamic_extent || Offset <= Extent,
275*635a8641SAndroid Build Coastguard Worker                   "Offset must not exceed Extent");
276*635a8641SAndroid Build Coastguard Worker     static_assert(Extent == dynamic_extent || Count == dynamic_extent ||
277*635a8641SAndroid Build Coastguard Worker                       Count <= Extent - Offset,
278*635a8641SAndroid Build Coastguard Worker                   "Count must not exceed Extent - Offset");
279*635a8641SAndroid Build Coastguard Worker     CHECK(Extent != dynamic_extent || Offset <= size());
280*635a8641SAndroid Build Coastguard Worker     CHECK(Extent != dynamic_extent || Count == dynamic_extent ||
281*635a8641SAndroid Build Coastguard Worker           Count <= size() - Offset);
282*635a8641SAndroid Build Coastguard Worker     return {data() + Offset, Count != dynamic_extent ? Count : size() - Offset};
283*635a8641SAndroid Build Coastguard Worker   }
284*635a8641SAndroid Build Coastguard Worker 
285*635a8641SAndroid Build Coastguard Worker   constexpr span<T, dynamic_extent> first(size_t count) const noexcept {
286*635a8641SAndroid Build Coastguard Worker     // Note: CHECK_LE is not constexpr, hence regular CHECK must be used.
287*635a8641SAndroid Build Coastguard Worker     CHECK(count <= size());
288*635a8641SAndroid Build Coastguard Worker     return {data(), count};
289*635a8641SAndroid Build Coastguard Worker   }
290*635a8641SAndroid Build Coastguard Worker 
291*635a8641SAndroid Build Coastguard Worker   constexpr span<T, dynamic_extent> last(size_t count) const noexcept {
292*635a8641SAndroid Build Coastguard Worker     // Note: CHECK_LE is not constexpr, hence regular CHECK must be used.
293*635a8641SAndroid Build Coastguard Worker     CHECK(count <= size());
294*635a8641SAndroid Build Coastguard Worker     return {data() + (size() - count), count};
295*635a8641SAndroid Build Coastguard Worker   }
296*635a8641SAndroid Build Coastguard Worker 
297*635a8641SAndroid Build Coastguard Worker   constexpr span<T, dynamic_extent> subspan(size_t offset,
298*635a8641SAndroid Build Coastguard Worker                                             size_t count = dynamic_extent) const
299*635a8641SAndroid Build Coastguard Worker       noexcept {
300*635a8641SAndroid Build Coastguard Worker     // Note: CHECK_LE is not constexpr, hence regular CHECK must be used.
301*635a8641SAndroid Build Coastguard Worker     CHECK(offset <= size());
302*635a8641SAndroid Build Coastguard Worker     CHECK(count == dynamic_extent || count <= size() - offset);
303*635a8641SAndroid Build Coastguard Worker     return {data() + offset, count != dynamic_extent ? count : size() - offset};
304*635a8641SAndroid Build Coastguard Worker   }
305*635a8641SAndroid Build Coastguard Worker 
306*635a8641SAndroid Build Coastguard Worker   // [span.obs], span observers
307*635a8641SAndroid Build Coastguard Worker   constexpr size_t size() const noexcept { return size_; }
308*635a8641SAndroid Build Coastguard Worker   constexpr size_t size_bytes() const noexcept { return size() * sizeof(T); }
309*635a8641SAndroid Build Coastguard Worker   constexpr bool empty() const noexcept { return size() == 0; }
310*635a8641SAndroid Build Coastguard Worker 
311*635a8641SAndroid Build Coastguard Worker   // [span.elem], span element access
312*635a8641SAndroid Build Coastguard Worker   constexpr T& operator[](size_t idx) const noexcept {
313*635a8641SAndroid Build Coastguard Worker     // Note: CHECK_LT is not constexpr, hence regular CHECK must be used.
314*635a8641SAndroid Build Coastguard Worker     CHECK(idx < size());
315*635a8641SAndroid Build Coastguard Worker     return *(data() + idx);
316*635a8641SAndroid Build Coastguard Worker   }
317*635a8641SAndroid Build Coastguard Worker 
318*635a8641SAndroid Build Coastguard Worker   constexpr T& operator()(size_t idx) const noexcept {
319*635a8641SAndroid Build Coastguard Worker     // Note: CHECK_LT is not constexpr, hence regular CHECK must be used.
320*635a8641SAndroid Build Coastguard Worker     CHECK(idx < size());
321*635a8641SAndroid Build Coastguard Worker     return *(data() + idx);
322*635a8641SAndroid Build Coastguard Worker   }
323*635a8641SAndroid Build Coastguard Worker 
324*635a8641SAndroid Build Coastguard Worker   constexpr T* data() const noexcept { return data_; }
325*635a8641SAndroid Build Coastguard Worker 
326*635a8641SAndroid Build Coastguard Worker   // [span.iter], span iterator support
327*635a8641SAndroid Build Coastguard Worker   constexpr iterator begin() const noexcept { return data(); }
328*635a8641SAndroid Build Coastguard Worker   constexpr iterator end() const noexcept { return data() + size(); }
329*635a8641SAndroid Build Coastguard Worker 
330*635a8641SAndroid Build Coastguard Worker   constexpr const_iterator cbegin() const noexcept { return begin(); }
331*635a8641SAndroid Build Coastguard Worker   constexpr const_iterator cend() const noexcept { return end(); }
332*635a8641SAndroid Build Coastguard Worker 
333*635a8641SAndroid Build Coastguard Worker   constexpr reverse_iterator rbegin() const noexcept {
334*635a8641SAndroid Build Coastguard Worker     return reverse_iterator(end());
335*635a8641SAndroid Build Coastguard Worker   }
336*635a8641SAndroid Build Coastguard Worker   constexpr reverse_iterator rend() const noexcept {
337*635a8641SAndroid Build Coastguard Worker     return reverse_iterator(begin());
338*635a8641SAndroid Build Coastguard Worker   }
339*635a8641SAndroid Build Coastguard Worker 
340*635a8641SAndroid Build Coastguard Worker   constexpr const_reverse_iterator crbegin() const noexcept {
341*635a8641SAndroid Build Coastguard Worker     return const_reverse_iterator(cend());
342*635a8641SAndroid Build Coastguard Worker   }
343*635a8641SAndroid Build Coastguard Worker   constexpr const_reverse_iterator crend() const noexcept {
344*635a8641SAndroid Build Coastguard Worker     return const_reverse_iterator(cbegin());
345*635a8641SAndroid Build Coastguard Worker   }
346*635a8641SAndroid Build Coastguard Worker 
347*635a8641SAndroid Build Coastguard Worker  private:
348*635a8641SAndroid Build Coastguard Worker   T* data_;
349*635a8641SAndroid Build Coastguard Worker   size_t size_;
350*635a8641SAndroid Build Coastguard Worker };
351*635a8641SAndroid Build Coastguard Worker 
352*635a8641SAndroid Build Coastguard Worker // span<T, Extent>::extent can not be declared inline prior to C++17, hence this
353*635a8641SAndroid Build Coastguard Worker // definition is required.
354*635a8641SAndroid Build Coastguard Worker template <class T, size_t Extent>
355*635a8641SAndroid Build Coastguard Worker constexpr size_t span<T, Extent>::extent;
356*635a8641SAndroid Build Coastguard Worker 
357*635a8641SAndroid Build Coastguard Worker // [span.comparison], span comparison operators
358*635a8641SAndroid Build Coastguard Worker // Relational operators. Equality is a element-wise comparison.
359*635a8641SAndroid Build Coastguard Worker template <typename T, size_t X, typename U, size_t Y>
360*635a8641SAndroid Build Coastguard Worker constexpr bool operator==(span<T, X> lhs, span<U, Y> rhs) noexcept {
361*635a8641SAndroid Build Coastguard Worker   return std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend());
362*635a8641SAndroid Build Coastguard Worker }
363*635a8641SAndroid Build Coastguard Worker 
364*635a8641SAndroid Build Coastguard Worker template <typename T, size_t X, typename U, size_t Y>
365*635a8641SAndroid Build Coastguard Worker constexpr bool operator!=(span<T, X> lhs, span<U, Y> rhs) noexcept {
366*635a8641SAndroid Build Coastguard Worker   return !(lhs == rhs);
367*635a8641SAndroid Build Coastguard Worker }
368*635a8641SAndroid Build Coastguard Worker 
369*635a8641SAndroid Build Coastguard Worker template <typename T, size_t X, typename U, size_t Y>
370*635a8641SAndroid Build Coastguard Worker constexpr bool operator<(span<T, X> lhs, span<U, Y> rhs) noexcept {
371*635a8641SAndroid Build Coastguard Worker   return std::lexicographical_compare(lhs.cbegin(), lhs.cend(), rhs.cbegin(),
372*635a8641SAndroid Build Coastguard Worker                                       rhs.cend());
373*635a8641SAndroid Build Coastguard Worker }
374*635a8641SAndroid Build Coastguard Worker 
375*635a8641SAndroid Build Coastguard Worker template <typename T, size_t X, typename U, size_t Y>
376*635a8641SAndroid Build Coastguard Worker constexpr bool operator<=(span<T, X> lhs, span<U, Y> rhs) noexcept {
377*635a8641SAndroid Build Coastguard Worker   return !(rhs < lhs);
378*635a8641SAndroid Build Coastguard Worker }
379*635a8641SAndroid Build Coastguard Worker 
380*635a8641SAndroid Build Coastguard Worker template <typename T, size_t X, typename U, size_t Y>
381*635a8641SAndroid Build Coastguard Worker constexpr bool operator>(span<T, X> lhs, span<U, Y> rhs) noexcept {
382*635a8641SAndroid Build Coastguard Worker   return rhs < lhs;
383*635a8641SAndroid Build Coastguard Worker }
384*635a8641SAndroid Build Coastguard Worker 
385*635a8641SAndroid Build Coastguard Worker template <typename T, size_t X, typename U, size_t Y>
386*635a8641SAndroid Build Coastguard Worker constexpr bool operator>=(span<T, X> lhs, span<U, Y> rhs) noexcept {
387*635a8641SAndroid Build Coastguard Worker   return !(lhs < rhs);
388*635a8641SAndroid Build Coastguard Worker }
389*635a8641SAndroid Build Coastguard Worker 
390*635a8641SAndroid Build Coastguard Worker // [span.objectrep], views of object representation
391*635a8641SAndroid Build Coastguard Worker template <typename T, size_t X>
392*635a8641SAndroid Build Coastguard Worker span<const uint8_t, (X == dynamic_extent ? dynamic_extent : sizeof(T) * X)>
393*635a8641SAndroid Build Coastguard Worker as_bytes(span<T, X> s) noexcept {
394*635a8641SAndroid Build Coastguard Worker   return {reinterpret_cast<const uint8_t*>(s.data()), s.size_bytes()};
395*635a8641SAndroid Build Coastguard Worker }
396*635a8641SAndroid Build Coastguard Worker 
397*635a8641SAndroid Build Coastguard Worker template <typename T,
398*635a8641SAndroid Build Coastguard Worker           size_t X,
399*635a8641SAndroid Build Coastguard Worker           typename = std::enable_if_t<!std::is_const<T>::value>>
400*635a8641SAndroid Build Coastguard Worker span<uint8_t, (X == dynamic_extent ? dynamic_extent : sizeof(T) * X)>
401*635a8641SAndroid Build Coastguard Worker as_writable_bytes(span<T, X> s) noexcept {
402*635a8641SAndroid Build Coastguard Worker   return {reinterpret_cast<uint8_t*>(s.data()), s.size_bytes()};
403*635a8641SAndroid Build Coastguard Worker }
404*635a8641SAndroid Build Coastguard Worker 
405*635a8641SAndroid Build Coastguard Worker // Type-deducing helpers for constructing a span.
406*635a8641SAndroid Build Coastguard Worker template <typename T>
407*635a8641SAndroid Build Coastguard Worker constexpr span<T> make_span(T* data, size_t size) noexcept {
408*635a8641SAndroid Build Coastguard Worker   return {data, size};
409*635a8641SAndroid Build Coastguard Worker }
410*635a8641SAndroid Build Coastguard Worker 
411*635a8641SAndroid Build Coastguard Worker template <typename T>
412*635a8641SAndroid Build Coastguard Worker constexpr span<T> make_span(T* begin, T* end) noexcept {
413*635a8641SAndroid Build Coastguard Worker   return {begin, end};
414*635a8641SAndroid Build Coastguard Worker }
415*635a8641SAndroid Build Coastguard Worker 
416*635a8641SAndroid Build Coastguard Worker template <typename T, size_t N>
417*635a8641SAndroid Build Coastguard Worker constexpr span<T, N> make_span(T (&array)[N]) noexcept {
418*635a8641SAndroid Build Coastguard Worker   return array;
419*635a8641SAndroid Build Coastguard Worker }
420*635a8641SAndroid Build Coastguard Worker 
421*635a8641SAndroid Build Coastguard Worker template <typename T, size_t N>
422*635a8641SAndroid Build Coastguard Worker constexpr span<T, N> make_span(std::array<T, N>& array) noexcept {
423*635a8641SAndroid Build Coastguard Worker   return array;
424*635a8641SAndroid Build Coastguard Worker }
425*635a8641SAndroid Build Coastguard Worker 
426*635a8641SAndroid Build Coastguard Worker template <typename T, size_t N>
427*635a8641SAndroid Build Coastguard Worker constexpr span<const T, N> make_span(const std::array<T, N>& array) noexcept {
428*635a8641SAndroid Build Coastguard Worker   return array;
429*635a8641SAndroid Build Coastguard Worker }
430*635a8641SAndroid Build Coastguard Worker 
431*635a8641SAndroid Build Coastguard Worker template <typename Container,
432*635a8641SAndroid Build Coastguard Worker           typename T = typename Container::value_type,
433*635a8641SAndroid Build Coastguard Worker           typename = internal::EnableIfSpanCompatibleContainer<Container&, T>>
434*635a8641SAndroid Build Coastguard Worker constexpr span<T> make_span(Container& container) noexcept {
435*635a8641SAndroid Build Coastguard Worker   return container;
436*635a8641SAndroid Build Coastguard Worker }
437*635a8641SAndroid Build Coastguard Worker 
438*635a8641SAndroid Build Coastguard Worker template <
439*635a8641SAndroid Build Coastguard Worker     typename Container,
440*635a8641SAndroid Build Coastguard Worker     typename T = const typename Container::value_type,
441*635a8641SAndroid Build Coastguard Worker     typename = internal::EnableIfSpanCompatibleContainer<const Container&, T>>
442*635a8641SAndroid Build Coastguard Worker constexpr span<T> make_span(const Container& container) noexcept {
443*635a8641SAndroid Build Coastguard Worker   return container;
444*635a8641SAndroid Build Coastguard Worker }
445*635a8641SAndroid Build Coastguard Worker 
446*635a8641SAndroid Build Coastguard Worker template <typename T, size_t X>
447*635a8641SAndroid Build Coastguard Worker constexpr span<T, X> make_span(const span<T, X>& span) noexcept {
448*635a8641SAndroid Build Coastguard Worker   return span;
449*635a8641SAndroid Build Coastguard Worker }
450*635a8641SAndroid Build Coastguard Worker 
451*635a8641SAndroid Build Coastguard Worker }  // namespace base
452*635a8641SAndroid Build Coastguard Worker 
453*635a8641SAndroid Build Coastguard Worker #endif  // BASE_CONTAINERS_SPAN_H_
454