• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2017 The Abseil Authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      https://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 // -----------------------------------------------------------------------------
17 // span.h
18 // -----------------------------------------------------------------------------
19 //
20 // This header file defines a `Span<T>` type for holding a reference to existing
21 // array data. The `Span` object, much like the `absl::string_view` object,
22 // does not own such data itself, and the data being referenced by the span must
23 // outlive the span itself. Unlike `view` type references, a span can hold a
24 // reference to mutable data (and can mutate it for underlying types of
25 // non-const T.) A span provides a lightweight way to pass a reference to such
26 // data.
27 //
28 // Additionally, this header file defines `MakeSpan()` and `MakeConstSpan()`
29 // factory functions, for clearly creating spans of type `Span<T>` or read-only
30 // `Span<const T>` when such types may be difficult to identify due to issues
31 // with implicit conversion.
32 //
33 // The C++20 draft standard includes a `std::span` type. As of June 2020, the
34 // differences between `absl::Span` and `std::span` are:
35 //    * `absl::Span` has `operator==` (which is likely a design bug,
36 //       per https://abseil.io/blog/20180531-regular-types)
37 //    * `absl::Span` has the factory functions `MakeSpan()` and
38 //      `MakeConstSpan()`
39 //    * bounds-checked access to `absl::Span` is accomplished with `at()`
40 //    * `absl::Span` has compiler-provided move and copy constructors and
41 //      assignment. This is due to them being specified as `constexpr`, but that
42 //      implies const in C++11.
43 //    * `absl::Span` has no `element_type` typedef
44 //    * A read-only `absl::Span<const T>` can be implicitly constructed from an
45 //      initializer list.
46 //    * `absl::Span` has no `bytes()`, `size_bytes()`, `as_bytes()`, or
47 //      `as_mutable_bytes()` methods
48 //    * `absl::Span` has no static extent template parameter, nor constructors
49 //      which exist only because of the static extent parameter.
50 //    * `absl::Span` has an explicit mutable-reference constructor
51 //
52 // For more information, see the class comments below.
53 #ifndef ABSL_TYPES_SPAN_H_
54 #define ABSL_TYPES_SPAN_H_
55 
56 #include <algorithm>
57 #include <cassert>
58 #include <cstddef>
59 #include <initializer_list>
60 #include <iterator>
61 #include <type_traits>
62 #include <utility>
63 
64 #include "absl/base/internal/throw_delegate.h"
65 #include "absl/base/macros.h"
66 #include "absl/base/optimization.h"
67 #include "absl/base/port.h"    // TODO(strel): remove this include
68 #include "absl/meta/type_traits.h"
69 #include "absl/types/internal/span.h"
70 
71 namespace absl {
72 ABSL_NAMESPACE_BEGIN
73 
74 //------------------------------------------------------------------------------
75 // Span
76 //------------------------------------------------------------------------------
77 //
78 // A `Span` is an "array reference" type for holding a reference of contiguous
79 // array data; the `Span` object does not and cannot own such data itself. A
80 // span provides an easy way to provide overloads for anything operating on
81 // contiguous sequences without needing to manage pointers and array lengths
82 // manually.
83 
84 // A span is conceptually a pointer (ptr) and a length (size) into an already
85 // existing array of contiguous memory; the array it represents references the
86 // elements "ptr[0] .. ptr[size-1]". Passing a properly-constructed `Span`
87 // instead of raw pointers avoids many issues related to index out of bounds
88 // errors.
89 //
90 // Spans may also be constructed from containers holding contiguous sequences.
91 // Such containers must supply `data()` and `size() const` methods (e.g
92 // `std::vector<T>`, `absl::InlinedVector<T, N>`). All implicit conversions to
93 // `absl::Span` from such containers will create spans of type `const T`;
94 // spans which can mutate their values (of type `T`) must use explicit
95 // constructors.
96 //
97 // A `Span<T>` is somewhat analogous to an `absl::string_view`, but for an array
98 // of elements of type `T`, and unlike an `absl::string_view`, a span can hold a
99 // reference to mutable data. A user of `Span` must ensure that the data being
100 // pointed to outlives the `Span` itself.
101 //
102 // You can construct a `Span<T>` in several ways:
103 //
104 //   * Explicitly from a reference to a container type
105 //   * Explicitly from a pointer and size
106 //   * Implicitly from a container type (but only for spans of type `const T`)
107 //   * Using the `MakeSpan()` or `MakeConstSpan()` factory functions.
108 //
109 // Examples:
110 //
111 //   // Construct a Span explicitly from a container:
112 //   std::vector<int> v = {1, 2, 3, 4, 5};
113 //   auto span = absl::Span<const int>(v);
114 //
115 //   // Construct a Span explicitly from a C-style array:
116 //   int a[5] =  {1, 2, 3, 4, 5};
117 //   auto span = absl::Span<const int>(a);
118 //
119 //   // Construct a Span implicitly from a container
120 //   void MyRoutine(absl::Span<const int> a) {
121 //     ...
122 //   }
123 //   std::vector v = {1,2,3,4,5};
124 //   MyRoutine(v)                     // convert to Span<const T>
125 //
126 // Note that `Span` objects, in addition to requiring that the memory they
127 // point to remains alive, must also ensure that such memory does not get
128 // reallocated. Therefore, to avoid undefined behavior, containers with
129 // associated spans should not invoke operations that may reallocate memory
130 // (such as resizing) or invalidate iterators into the container.
131 //
132 // One common use for a `Span` is when passing arguments to a routine that can
133 // accept a variety of array types (e.g. a `std::vector`, `absl::InlinedVector`,
134 // a C-style array, etc.). Instead of creating overloads for each case, you
135 // can simply specify a `Span` as the argument to such a routine.
136 //
137 // Example:
138 //
139 //   void MyRoutine(absl::Span<const int> a) {
140 //     ...
141 //   }
142 //
143 //   std::vector v = {1,2,3,4,5};
144 //   MyRoutine(v);
145 //
146 //   absl::InlinedVector<int, 4> my_inline_vector;
147 //   MyRoutine(my_inline_vector);
148 //
149 //   // Explicit constructor from pointer,size
150 //   int* my_array = new int[10];
151 //   MyRoutine(absl::Span<const int>(my_array, 10));
152 template <typename T>
153 class Span {
154  private:
155   // Used to determine whether a Span can be constructed from a container of
156   // type C.
157   template <typename C>
158   using EnableIfConvertibleFrom =
159       typename std::enable_if<span_internal::HasData<T, C>::value &&
160                               span_internal::HasSize<C>::value>::type;
161 
162   // Used to SFINAE-enable a function when the slice elements are const.
163   template <typename U>
164   using EnableIfConstView =
165       typename std::enable_if<std::is_const<T>::value, U>::type;
166 
167   // Used to SFINAE-enable a function when the slice elements are mutable.
168   template <typename U>
169   using EnableIfMutableView =
170       typename std::enable_if<!std::is_const<T>::value, U>::type;
171 
172  public:
173   using value_type = absl::remove_cv_t<T>;
174   using pointer = T*;
175   using const_pointer = const T*;
176   using reference = T&;
177   using const_reference = const T&;
178   using iterator = pointer;
179   using const_iterator = const_pointer;
180   using reverse_iterator = std::reverse_iterator<iterator>;
181   using const_reverse_iterator = std::reverse_iterator<const_iterator>;
182   using size_type = size_t;
183   using difference_type = ptrdiff_t;
184 
185   static const size_type npos = ~(size_type(0));
186 
Span()187   constexpr Span() noexcept : Span(nullptr, 0) {}
Span(pointer array,size_type length)188   constexpr Span(pointer array, size_type length) noexcept
189       : ptr_(array), len_(length) {}
190 
191   // Implicit conversion constructors
192   template <size_t N>
Span(T (& a)[N])193   constexpr Span(T (&a)[N]) noexcept  // NOLINT(runtime/explicit)
194       : Span(a, N) {}
195 
196   // Explicit reference constructor for a mutable `Span<T>` type. Can be
197   // replaced with MakeSpan() to infer the type parameter.
198   template <typename V, typename = EnableIfConvertibleFrom<V>,
199             typename = EnableIfMutableView<V>>
Span(V & v)200   explicit Span(V& v) noexcept  // NOLINT(runtime/references)
201       : Span(span_internal::GetData(v), v.size()) {}
202 
203   // Implicit reference constructor for a read-only `Span<const T>` type
204   template <typename V, typename = EnableIfConvertibleFrom<V>,
205             typename = EnableIfConstView<V>>
Span(const V & v)206   constexpr Span(const V& v) noexcept  // NOLINT(runtime/explicit)
207       : Span(span_internal::GetData(v), v.size()) {}
208 
209   // Implicit constructor from an initializer list, making it possible to pass a
210   // brace-enclosed initializer list to a function expecting a `Span`. Such
211   // spans constructed from an initializer list must be of type `Span<const T>`.
212   //
213   //   void Process(absl::Span<const int> x);
214   //   Process({1, 2, 3});
215   //
216   // Note that as always the array referenced by the span must outlive the span.
217   // Since an initializer list constructor acts as if it is fed a temporary
218   // array (cf. C++ standard [dcl.init.list]/5), it's safe to use this
219   // constructor only when the `std::initializer_list` itself outlives the span.
220   // In order to meet this requirement it's sufficient to ensure that neither
221   // the span nor a copy of it is used outside of the expression in which it's
222   // created:
223   //
224   //   // Assume that this function uses the array directly, not retaining any
225   //   // copy of the span or pointer to any of its elements.
226   //   void Process(absl::Span<const int> ints);
227   //
228   //   // Okay: the std::initializer_list<int> will reference a temporary array
229   //   // that isn't destroyed until after the call to Process returns.
230   //   Process({ 17, 19 });
231   //
232   //   // Not okay: the storage used by the std::initializer_list<int> is not
233   //   // allowed to be referenced after the first line.
234   //   absl::Span<const int> ints = { 17, 19 };
235   //   Process(ints);
236   //
237   //   // Not okay for the same reason as above: even when the elements of the
238   //   // initializer list expression are not temporaries the underlying array
239   //   // is, so the initializer list must still outlive the span.
240   //   const int foo = 17;
241   //   absl::Span<const int> ints = { foo };
242   //   Process(ints);
243   //
244   template <typename LazyT = T,
245             typename = EnableIfConstView<LazyT>>
Span(std::initializer_list<value_type> v)246   Span(
247       std::initializer_list<value_type> v) noexcept  // NOLINT(runtime/explicit)
248       : Span(v.begin(), v.size()) {}
249 
250   // Accessors
251 
252   // Span::data()
253   //
254   // Returns a pointer to the span's underlying array of data (which is held
255   // outside the span).
data()256   constexpr pointer data() const noexcept { return ptr_; }
257 
258   // Span::size()
259   //
260   // Returns the size of this span.
size()261   constexpr size_type size() const noexcept { return len_; }
262 
263   // Span::length()
264   //
265   // Returns the length (size) of this span.
length()266   constexpr size_type length() const noexcept { return size(); }
267 
268   // Span::empty()
269   //
270   // Returns a boolean indicating whether or not this span is considered empty.
empty()271   constexpr bool empty() const noexcept { return size() == 0; }
272 
273   // Span::operator[]
274   //
275   // Returns a reference to the i'th element of this span.
276   constexpr reference operator[](size_type i) const noexcept {
277     // MSVC 2015 accepts this as constexpr, but not ptr_[i]
278     return ABSL_HARDENING_ASSERT(i < size()), *(data() + i);
279   }
280 
281   // Span::at()
282   //
283   // Returns a reference to the i'th element of this span.
at(size_type i)284   constexpr reference at(size_type i) const {
285     return ABSL_PREDICT_TRUE(i < size())  //
286                ? *(data() + i)
287                : (base_internal::ThrowStdOutOfRange(
288                       "Span::at failed bounds check"),
289                   *(data() + i));
290   }
291 
292   // Span::front()
293   //
294   // Returns a reference to the first element of this span. The span must not
295   // be empty.
front()296   constexpr reference front() const noexcept {
297     return ABSL_HARDENING_ASSERT(size() > 0), *data();
298   }
299 
300   // Span::back()
301   //
302   // Returns a reference to the last element of this span. The span must not
303   // be empty.
back()304   constexpr reference back() const noexcept {
305     return ABSL_HARDENING_ASSERT(size() > 0), *(data() + size() - 1);
306   }
307 
308   // Span::begin()
309   //
310   // Returns an iterator pointing to the first element of this span, or `end()`
311   // if the span is empty.
begin()312   constexpr iterator begin() const noexcept { return data(); }
313 
314   // Span::cbegin()
315   //
316   // Returns a const iterator pointing to the first element of this span, or
317   // `end()` if the span is empty.
cbegin()318   constexpr const_iterator cbegin() const noexcept { return begin(); }
319 
320   // Span::end()
321   //
322   // Returns an iterator pointing just beyond the last element at the
323   // end of this span. This iterator acts as a placeholder; attempting to
324   // access it results in undefined behavior.
end()325   constexpr iterator end() const noexcept { return data() + size(); }
326 
327   // Span::cend()
328   //
329   // Returns a const iterator pointing just beyond the last element at the
330   // end of this span. This iterator acts as a placeholder; attempting to
331   // access it results in undefined behavior.
cend()332   constexpr const_iterator cend() const noexcept { return end(); }
333 
334   // Span::rbegin()
335   //
336   // Returns a reverse iterator pointing to the last element at the end of this
337   // span, or `rend()` if the span is empty.
rbegin()338   constexpr reverse_iterator rbegin() const noexcept {
339     return reverse_iterator(end());
340   }
341 
342   // Span::crbegin()
343   //
344   // Returns a const reverse iterator pointing to the last element at the end of
345   // this span, or `crend()` if the span is empty.
crbegin()346   constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); }
347 
348   // Span::rend()
349   //
350   // Returns a reverse iterator pointing just before the first element
351   // at the beginning of this span. This pointer acts as a placeholder;
352   // attempting to access its element results in undefined behavior.
rend()353   constexpr reverse_iterator rend() const noexcept {
354     return reverse_iterator(begin());
355   }
356 
357   // Span::crend()
358   //
359   // Returns a reverse const iterator pointing just before the first element
360   // at the beginning of this span. This pointer acts as a placeholder;
361   // attempting to access its element results in undefined behavior.
crend()362   constexpr const_reverse_iterator crend() const noexcept { return rend(); }
363 
364   // Span mutations
365 
366   // Span::remove_prefix()
367   //
368   // Removes the first `n` elements from the span.
remove_prefix(size_type n)369   void remove_prefix(size_type n) noexcept {
370     ABSL_HARDENING_ASSERT(size() >= n);
371     ptr_ += n;
372     len_ -= n;
373   }
374 
375   // Span::remove_suffix()
376   //
377   // Removes the last `n` elements from the span.
remove_suffix(size_type n)378   void remove_suffix(size_type n) noexcept {
379     ABSL_HARDENING_ASSERT(size() >= n);
380     len_ -= n;
381   }
382 
383   // Span::subspan()
384   //
385   // Returns a `Span` starting at element `pos` and of length `len`. Both `pos`
386   // and `len` are of type `size_type` and thus non-negative. Parameter `pos`
387   // must be <= size(). Any `len` value that points past the end of the span
388   // will be trimmed to at most size() - `pos`. A default `len` value of `npos`
389   // ensures the returned subspan continues until the end of the span.
390   //
391   // Examples:
392   //
393   //   std::vector<int> vec = {10, 11, 12, 13};
394   //   absl::MakeSpan(vec).subspan(1, 2);  // {11, 12}
395   //   absl::MakeSpan(vec).subspan(2, 8);  // {12, 13}
396   //   absl::MakeSpan(vec).subspan(1);     // {11, 12, 13}
397   //   absl::MakeSpan(vec).subspan(4);     // {}
398   //   absl::MakeSpan(vec).subspan(5);     // throws std::out_of_range
399   constexpr Span subspan(size_type pos = 0, size_type len = npos) const {
400     return (pos <= size())
401                ? Span(data() + pos, span_internal::Min(size() - pos, len))
402                : (base_internal::ThrowStdOutOfRange("pos > size()"), Span());
403   }
404 
405   // Span::first()
406   //
407   // Returns a `Span` containing first `len` elements. Parameter `len` is of
408   // type `size_type` and thus non-negative. `len` value must be <= size().
409   //
410   // Examples:
411   //
412   //   std::vector<int> vec = {10, 11, 12, 13};
413   //   absl::MakeSpan(vec).first(1);  // {10}
414   //   absl::MakeSpan(vec).first(3);  // {10, 11, 12}
415   //   absl::MakeSpan(vec).first(5);  // throws std::out_of_range
first(size_type len)416   constexpr Span first(size_type len) const {
417     return (len <= size())
418                ? Span(data(), len)
419                : (base_internal::ThrowStdOutOfRange("len > size()"), Span());
420   }
421 
422   // Span::last()
423   //
424   // Returns a `Span` containing last `len` elements. Parameter `len` is of
425   // type `size_type` and thus non-negative. `len` value must be <= size().
426   //
427   // Examples:
428   //
429   //   std::vector<int> vec = {10, 11, 12, 13};
430   //   absl::MakeSpan(vec).last(1);  // {13}
431   //   absl::MakeSpan(vec).last(3);  // {11, 12, 13}
432   //   absl::MakeSpan(vec).last(5);  // throws std::out_of_range
last(size_type len)433   constexpr Span last(size_type len) const {
434     return (len <= size())
435                ? Span(size() - len + data(), len)
436                : (base_internal::ThrowStdOutOfRange("len > size()"), Span());
437   }
438 
439   // Support for absl::Hash.
440   template <typename H>
AbslHashValue(H h,Span v)441   friend H AbslHashValue(H h, Span v) {
442     return H::combine(H::combine_contiguous(std::move(h), v.data(), v.size()),
443                       v.size());
444   }
445 
446  private:
447   pointer ptr_;
448   size_type len_;
449 };
450 
451 template <typename T>
452 const typename Span<T>::size_type Span<T>::npos;
453 
454 // Span relationals
455 
456 // Equality is compared element-by-element, while ordering is lexicographical.
457 // We provide three overloads for each operator to cover any combination on the
458 // left or right hand side of mutable Span<T>, read-only Span<const T>, and
459 // convertible-to-read-only Span<T>.
460 // TODO(zhangxy): Due to MSVC overload resolution bug with partial ordering
461 // template functions, 5 overloads per operator is needed as a workaround. We
462 // should update them to 3 overloads per operator using non-deduced context like
463 // string_view, i.e.
464 // - (Span<T>, Span<T>)
465 // - (Span<T>, non_deduced<Span<const T>>)
466 // - (non_deduced<Span<const T>>, Span<T>)
467 
468 // operator==
469 template <typename T>
470 bool operator==(Span<T> a, Span<T> b) {
471   return span_internal::EqualImpl<Span, const T>(a, b);
472 }
473 template <typename T>
474 bool operator==(Span<const T> a, Span<T> b) {
475   return span_internal::EqualImpl<Span, const T>(a, b);
476 }
477 template <typename T>
478 bool operator==(Span<T> a, Span<const T> b) {
479   return span_internal::EqualImpl<Span, const T>(a, b);
480 }
481 template <
482     typename T, typename U,
483     typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
484 bool operator==(const U& a, Span<T> b) {
485   return span_internal::EqualImpl<Span, const T>(a, b);
486 }
487 template <
488     typename T, typename U,
489     typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
490 bool operator==(Span<T> a, const U& b) {
491   return span_internal::EqualImpl<Span, const T>(a, b);
492 }
493 
494 // operator!=
495 template <typename T>
496 bool operator!=(Span<T> a, Span<T> b) {
497   return !(a == b);
498 }
499 template <typename T>
500 bool operator!=(Span<const T> a, Span<T> b) {
501   return !(a == b);
502 }
503 template <typename T>
504 bool operator!=(Span<T> a, Span<const T> b) {
505   return !(a == b);
506 }
507 template <
508     typename T, typename U,
509     typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
510 bool operator!=(const U& a, Span<T> b) {
511   return !(a == b);
512 }
513 template <
514     typename T, typename U,
515     typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
516 bool operator!=(Span<T> a, const U& b) {
517   return !(a == b);
518 }
519 
520 // operator<
521 template <typename T>
522 bool operator<(Span<T> a, Span<T> b) {
523   return span_internal::LessThanImpl<Span, const T>(a, b);
524 }
525 template <typename T>
526 bool operator<(Span<const T> a, Span<T> b) {
527   return span_internal::LessThanImpl<Span, const T>(a, b);
528 }
529 template <typename T>
530 bool operator<(Span<T> a, Span<const T> b) {
531   return span_internal::LessThanImpl<Span, const T>(a, b);
532 }
533 template <
534     typename T, typename U,
535     typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
536 bool operator<(const U& a, Span<T> b) {
537   return span_internal::LessThanImpl<Span, const T>(a, b);
538 }
539 template <
540     typename T, typename U,
541     typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
542 bool operator<(Span<T> a, const U& b) {
543   return span_internal::LessThanImpl<Span, const T>(a, b);
544 }
545 
546 // operator>
547 template <typename T>
548 bool operator>(Span<T> a, Span<T> b) {
549   return b < a;
550 }
551 template <typename T>
552 bool operator>(Span<const T> a, Span<T> b) {
553   return b < a;
554 }
555 template <typename T>
556 bool operator>(Span<T> a, Span<const T> b) {
557   return b < a;
558 }
559 template <
560     typename T, typename U,
561     typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
562 bool operator>(const U& a, Span<T> b) {
563   return b < a;
564 }
565 template <
566     typename T, typename U,
567     typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
568 bool operator>(Span<T> a, const U& b) {
569   return b < a;
570 }
571 
572 // operator<=
573 template <typename T>
574 bool operator<=(Span<T> a, Span<T> b) {
575   return !(b < a);
576 }
577 template <typename T>
578 bool operator<=(Span<const T> a, Span<T> b) {
579   return !(b < a);
580 }
581 template <typename T>
582 bool operator<=(Span<T> a, Span<const T> b) {
583   return !(b < a);
584 }
585 template <
586     typename T, typename U,
587     typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
588 bool operator<=(const U& a, Span<T> b) {
589   return !(b < a);
590 }
591 template <
592     typename T, typename U,
593     typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
594 bool operator<=(Span<T> a, const U& b) {
595   return !(b < a);
596 }
597 
598 // operator>=
599 template <typename T>
600 bool operator>=(Span<T> a, Span<T> b) {
601   return !(a < b);
602 }
603 template <typename T>
604 bool operator>=(Span<const T> a, Span<T> b) {
605   return !(a < b);
606 }
607 template <typename T>
608 bool operator>=(Span<T> a, Span<const T> b) {
609   return !(a < b);
610 }
611 template <
612     typename T, typename U,
613     typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
614 bool operator>=(const U& a, Span<T> b) {
615   return !(a < b);
616 }
617 template <
618     typename T, typename U,
619     typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
620 bool operator>=(Span<T> a, const U& b) {
621   return !(a < b);
622 }
623 
624 // MakeSpan()
625 //
626 // Constructs a mutable `Span<T>`, deducing `T` automatically from either a
627 // container or pointer+size.
628 //
629 // Because a read-only `Span<const T>` is implicitly constructed from container
630 // types regardless of whether the container itself is a const container,
631 // constructing mutable spans of type `Span<T>` from containers requires
632 // explicit constructors. The container-accepting version of `MakeSpan()`
633 // deduces the type of `T` by the constness of the pointer received from the
634 // container's `data()` member. Similarly, the pointer-accepting version returns
635 // a `Span<const T>` if `T` is `const`, and a `Span<T>` otherwise.
636 //
637 // Examples:
638 //
639 //   void MyRoutine(absl::Span<MyComplicatedType> a) {
640 //     ...
641 //   };
642 //   // my_vector is a container of non-const types
643 //   std::vector<MyComplicatedType> my_vector;
644 //
645 //   // Constructing a Span implicitly attempts to create a Span of type
646 //   // `Span<const T>`
647 //   MyRoutine(my_vector);                // error, type mismatch
648 //
649 //   // Explicitly constructing the Span is verbose
650 //   MyRoutine(absl::Span<MyComplicatedType>(my_vector));
651 //
652 //   // Use MakeSpan() to make an absl::Span<T>
653 //   MyRoutine(absl::MakeSpan(my_vector));
654 //
655 //   // Construct a span from an array ptr+size
656 //   absl::Span<T> my_span() {
657 //     return absl::MakeSpan(&array[0], num_elements_);
658 //   }
659 //
660 template <int&... ExplicitArgumentBarrier, typename T>
MakeSpan(T * ptr,size_t size)661 constexpr Span<T> MakeSpan(T* ptr, size_t size) noexcept {
662   return Span<T>(ptr, size);
663 }
664 
665 template <int&... ExplicitArgumentBarrier, typename T>
MakeSpan(T * begin,T * end)666 Span<T> MakeSpan(T* begin, T* end) noexcept {
667   return ABSL_HARDENING_ASSERT(begin <= end), Span<T>(begin, end - begin);
668 }
669 
670 template <int&... ExplicitArgumentBarrier, typename C>
671 constexpr auto MakeSpan(C& c) noexcept  // NOLINT(runtime/references)
672     -> decltype(absl::MakeSpan(span_internal::GetData(c), c.size())) {
673   return MakeSpan(span_internal::GetData(c), c.size());
674 }
675 
676 template <int&... ExplicitArgumentBarrier, typename T, size_t N>
MakeSpan(T (& array)[N])677 constexpr Span<T> MakeSpan(T (&array)[N]) noexcept {
678   return Span<T>(array, N);
679 }
680 
681 // MakeConstSpan()
682 //
683 // Constructs a `Span<const T>` as with `MakeSpan`, deducing `T` automatically,
684 // but always returning a `Span<const T>`.
685 //
686 // Examples:
687 //
688 //   void ProcessInts(absl::Span<const int> some_ints);
689 //
690 //   // Call with a pointer and size.
691 //   int array[3] = { 0, 0, 0 };
692 //   ProcessInts(absl::MakeConstSpan(&array[0], 3));
693 //
694 //   // Call with a [begin, end) pair.
695 //   ProcessInts(absl::MakeConstSpan(&array[0], &array[3]));
696 //
697 //   // Call directly with an array.
698 //   ProcessInts(absl::MakeConstSpan(array));
699 //
700 //   // Call with a contiguous container.
701 //   std::vector<int> some_ints = ...;
702 //   ProcessInts(absl::MakeConstSpan(some_ints));
703 //   ProcessInts(absl::MakeConstSpan(std::vector<int>{ 0, 0, 0 }));
704 //
705 template <int&... ExplicitArgumentBarrier, typename T>
MakeConstSpan(T * ptr,size_t size)706 constexpr Span<const T> MakeConstSpan(T* ptr, size_t size) noexcept {
707   return Span<const T>(ptr, size);
708 }
709 
710 template <int&... ExplicitArgumentBarrier, typename T>
MakeConstSpan(T * begin,T * end)711 Span<const T> MakeConstSpan(T* begin, T* end) noexcept {
712   return ABSL_HARDENING_ASSERT(begin <= end), Span<const T>(begin, end - begin);
713 }
714 
715 template <int&... ExplicitArgumentBarrier, typename C>
716 constexpr auto MakeConstSpan(const C& c) noexcept -> decltype(MakeSpan(c)) {
717   return MakeSpan(c);
718 }
719 
720 template <int&... ExplicitArgumentBarrier, typename T, size_t N>
MakeConstSpan(const T (& array)[N])721 constexpr Span<const T> MakeConstSpan(const T (&array)[N]) noexcept {
722   return Span<const T>(array, N);
723 }
724 ABSL_NAMESPACE_END
725 }  // namespace absl
726 #endif  // ABSL_TYPES_SPAN_H_
727