aboutsummaryrefslogtreecommitdiffhomepage
path: root/absl/types/span.h
diff options
context:
space:
mode:
authorGravatar misterg <misterg@google.com>2017-09-19 16:54:40 -0400
committerGravatar misterg <misterg@google.com>2017-09-19 16:54:40 -0400
commitc2e754829628d1e9b7a16b3389cfdace76950fdf (patch)
tree5a7f056f44e27c30e10025113b644f0b3b5801fc /absl/types/span.h
Initial Commit
Diffstat (limited to 'absl/types/span.h')
-rw-r--r--absl/types/span.h738
1 files changed, 738 insertions, 0 deletions
diff --git a/absl/types/span.h b/absl/types/span.h
new file mode 100644
index 0000000..0e26fd4
--- /dev/null
+++ b/absl/types/span.h
@@ -0,0 +1,738 @@
+//
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// span.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines a `Span<T>` type for holding a view of an existing
+// array of data. The `Span` object, much like the `absl::string_view` object,
+// does not own such data itself. A span provides a lightweight way to pass
+// around view of such data.
+//
+// Additionally, this header file defines `MakeSpan()` and `MakeConstSpan()`
+// factory functions, for clearly creating spans of type `Span<T>` or read-only
+// `Span<const T>` when such types may be difficult to identify due to issues
+// with implicit conversion.
+//
+// The C++ standards committee currently has a proposal for a `std::span` type,
+// (http://wg21.link/p0122), which is not yet part of the standard (though may
+// become part of C++20). As of August 2017, the differences between
+// `absl::Span` and this proposal are:
+// * `absl::Span` uses `size_t` for `size_type`
+// * `absl::Span` has no `operator()`
+// * `absl::Span` has no constructors for `std::unique_ptr` or
+// `std::shared_ptr`
+// * `absl::span` has the factory functions `MakeSpan()` and
+// `MakeConstSpan()`
+// * `absl::Span` has `front()` and `back()` methods
+// * bounds-checked access to `absl::Span` is accomplished with `at()`
+// * `absl::Span` has compiler-provided move and copy constructors and
+// assignment. This is due to them being specified as `constexpr`, but that
+// implies const in C++11.
+// * `absl::Span` has no `element_type` or `index_type` typedefs
+// * A read-only `absl::Span<const T>` can be implicitly constructed from an
+// initializer list.
+// * `absl::Span` has no `bytes()`, `size_bytes()`, `as_bytes()`, or
+// `as_mutable_bytes()` methods
+// * `absl::Span` has no static extent template parameter, nor constructors
+// which exist only because of the static extent parameter.
+// * `absl::Span` has an explicit mutable-reference constructor
+//
+// For more information, see the class comments below.
+#ifndef ABSL_TYPES_SPAN_H_
+#define ABSL_TYPES_SPAN_H_
+
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <initializer_list>
+#include <iterator>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+#include "absl/algorithm/algorithm.h"
+#include "absl/base/internal/throw_delegate.h"
+#include "absl/base/macros.h"
+#include "absl/base/optimization.h"
+#include "absl/base/port.h"
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+
+template <typename T>
+class Span;
+
+namespace span_internal {
+// A constexpr min function
+constexpr size_t Min(size_t a, size_t b) noexcept { return a < b ? a : b; }
+
+// Wrappers for access to container data pointers.
+template <typename C>
+constexpr auto GetDataImpl(C& c, char) noexcept // NOLINT(runtime/references)
+ -> decltype(c.data()) {
+ return c.data();
+}
+
+// Before C++17, std::string::data returns a const char* in all cases.
+inline char* GetDataImpl(std::string& s, // NOLINT(runtime/references)
+ int) noexcept {
+ return &s[0];
+}
+
+template <typename C>
+constexpr auto GetData(C& c) noexcept // NOLINT(runtime/references)
+ -> decltype(GetDataImpl(c, 0)) {
+ return GetDataImpl(c, 0);
+}
+
+// Detection idioms for size() and data().
+template <typename C>
+using HasSize =
+ std::is_integral<absl::decay_t<decltype(std::declval<C&>().size())>>;
+
+// We want to enable conversion from vector<T*> to Span<const T* const> but
+// disable conversion from vector<Derived> to Span<Base>. Here we use
+// the fact that U** is convertible to Q* const* if and only if Q is the same
+// type or a more cv-qualified version of U. We also decay the result type of
+// data() to avoid problems with classes which have a member function data()
+// which returns a reference.
+template <typename T, typename C>
+using HasData =
+ std::is_convertible<absl::decay_t<decltype(GetData(std::declval<C&>()))>*,
+ T* const*>;
+
+// Extracts value type from a Container
+template <typename C>
+struct ElementType {
+ using type = typename absl::remove_reference_t<C>::value_type;
+};
+
+template <typename T, size_t N>
+struct ElementType<T (&)[N]> {
+ using type = T;
+};
+
+template <typename C>
+using ElementT = typename ElementType<C>::type;
+
+template <typename T>
+using EnableIfMutable =
+ typename std::enable_if<!std::is_const<T>::value, int>::type;
+
+template <typename T>
+bool EqualImpl(Span<T> a, Span<T> b) {
+ static_assert(std::is_const<T>::value, "");
+ return absl::equal(a.begin(), a.end(), b.begin(), b.end());
+}
+
+template <typename T>
+bool LessThanImpl(Span<T> a, Span<T> b) {
+ static_assert(std::is_const<T>::value, "");
+ return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
+}
+
+// The `IsConvertible` classes here are needed because of the
+// `std::is_convertible` bug in libcxx when compiled with GCC. This build
+// configuration is used by Android NDK toolchain. Reference link:
+// https://bugs.llvm.org/show_bug.cgi?id=27538.
+template <typename From, typename To>
+struct IsConvertibleHelper {
+ private:
+ static std::true_type test(To);
+ static std::false_type test(...);
+
+ public:
+ using type = decltype(test(std::declval<From>()));
+};
+
+template <typename From, typename To>
+struct IsConvertible : IsConvertibleHelper<From, To>::type {};
+
+// TODO(zhangxy): replace `IsConvertible` with `std::is_convertible` once the
+// older version of libcxx is not supported.
+template <typename From, typename To>
+using EnableIfConvertibleToSpanConst =
+ typename std::enable_if<IsConvertible<From, Span<const To>>::value>::type;
+} // namespace span_internal
+
+//------------------------------------------------------------------------------
+// Span
+//------------------------------------------------------------------------------
+//
+// A `Span` is an "array view" type for holding a view of a contiguous data
+// array; the `Span` object does not and cannot own such data itself. A span
+// provides an easy way to provide overloads for anything operating on
+// contiguous sequences without needing to manage pointers and array lengths
+// manually.
+
+// A span is conceptually a pointer (ptr) and a length (size) into an already
+// existing array of contiguous memory; the array it represents references the
+// elements "ptr[0] .. ptr[size-1]". Passing a properly-constructed `Span`
+// instead of raw pointers avoids many issues related to index out of bounds
+// errors.
+//
+// Spans may also be constructed from containers holding contiguous sequences.
+// Such containers must supply `data()` and `size() const` methods (e.g
+// `std::vector<T>`, `absl::InlinedVector<T, N>`). All implicit conversions to
+// `absl::Span` from such containers will create spans of type `const T`;
+// spans which can mutate their values (of type `T`) must use explicit
+// constructors.
+//
+// A `Span<T>` is somewhat analogous to an `absl::string_view`, but for an array
+// of elements of type `T`. A user of `Span` must ensure that the data being
+// pointed to outlives the `Span` itself.
+//
+// You can construct a `Span<T>` in several ways:
+//
+// * Explicitly from a reference to a container type
+// * Explicitly from a pointer and size
+// * Implicitly from a container type (but only for spans of type `const T`)
+// * Using the `MakeSpan()` or `MakeConstSpan()` factory functions.
+//
+// Examples:
+//
+// // Construct a Span explicitly from a container:
+// std::vector<int> v = {1, 2, 3, 4, 5};
+// auto span = absl::Span<const int>(v);
+//
+// // Construct a Span explicitly from a C-style array:
+// int a[5] = {1, 2, 3, 4, 5};
+// auto span = absl::Span<const int>(a);
+//
+// // Construct a Span implicitly from a container
+// void MyRoutine(absl::Span<const int> a) {
+// ...
+// };
+// std::vector v = {1,2,3,4,5};
+// MyRoutine(v) // convert to Span<const T>
+//
+// Note that `Span` objects, in addition to requiring that the memory they
+// point to remains alive, must also ensure that such memory does not get
+// reallocated. Therefore, to avoid undefined behavior, containers with
+// associated span views should not invoke operations that may reallocate memory
+// (such as resizing) or invalidate iterarors into the container.
+//
+// One common use for a `Span` is when passing arguments to a routine that can
+// accept a variety of array types (e.g. a `std::vector`, `absl::InlinedVector`,
+// a C-style array, etc.). Instead of creating overloads for each case, you
+// can simply specify a `Span` as the argument to such a routine.
+//
+// Example:
+//
+// void MyRoutine(absl::Span<const int> a) {
+// ...
+// };
+//
+// std::vector v = {1,2,3,4,5};
+// MyRoutine(v);
+//
+// absl::InlinedVector<int, 4> my_inline_vector;
+// MyRoutine(my_inline_vector);
+//
+// // Explicit constructor from pointer,size
+// int* my_array = new int[10];
+// MyRoutine(absl::Span<const int>(my_array, 10));
+template <typename T>
+class Span {
+ private:
+ // Used to determine whether a Span can be constructed from a container of
+ // type C.
+ template <typename C>
+ using EnableIfConvertibleFrom =
+ typename std::enable_if<span_internal::HasData<T, C>::value &&
+ span_internal::HasSize<C>::value>::type;
+
+ // Used to SFINAE-enable a function when the slice elements are const.
+ template <typename U>
+ using EnableIfConstView =
+ typename std::enable_if<std::is_const<T>::value, U>::type;
+
+ // Used to SFINAE-enable a function when the slice elements are mutable.
+ template <typename U>
+ using EnableIfMutableView =
+ typename std::enable_if<!std::is_const<T>::value, U>::type;
+
+ public:
+ using value_type = absl::remove_cv_t<T>;
+ using pointer = T*;
+ using const_pointer = const T*;
+ using reference = T&;
+ using const_reference = const T&;
+ using iterator = pointer;
+ using const_iterator = const_pointer;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+ using size_type = size_t;
+ using difference_type = ptrdiff_t;
+
+ static const size_type npos = -1;
+
+ constexpr Span() noexcept : Span(nullptr, 0) {}
+ constexpr Span(pointer array, size_type length) noexcept
+ : ptr_(array), len_(length) {}
+
+ // Implicit conversion constructors
+ template <size_t N>
+ constexpr Span(T (&a)[N]) noexcept // NOLINT(runtime/explicit)
+ : Span(a, N) {}
+
+ // Explicit reference constructor for a mutable `Span<T>` type
+ template <typename V, typename = EnableIfConvertibleFrom<V>,
+ typename = EnableIfMutableView<V>>
+ explicit Span(V& v) noexcept // NOLINT(runtime/references)
+ : Span(span_internal::GetData(v), v.size()) {}
+
+ // Implicit reference constructor for a read-only `Span<const T>` type
+ template <typename V, typename = EnableIfConvertibleFrom<V>,
+ typename = EnableIfConstView<V>>
+ constexpr Span(const V& v) noexcept // NOLINT(runtime/explicit)
+ : Span(span_internal::GetData(v), v.size()) {}
+
+ // Implicit constructor from an initializer list, making it possible to pass a
+ // brace-enclosed initializer list to a function expecting a `Span`. Such
+ // spans constructed from an initializer list must be of type `Span<const T>`.
+ //
+ // void Process(absl::Span<const int> x);
+ // Process({1, 2, 3});
+ //
+ // Note that as always the array referenced by the span must outlive the span.
+ // Since an initializer list constructor acts as if it is fed a temporary
+ // array (cf. C++ standard [dcl.init.list]/5), it's safe to use this
+ // constructor only when the `std::initializer_list` itself outlives the span.
+ // In order to meet this requirement it's sufficient to ensure that neither
+ // the span nor a copy of it is used outside of the expression in which it's
+ // created:
+ //
+ // // Assume that this function uses the array directly, not retaining any
+ // // copy of the span or pointer to any of its elements.
+ // void Process(absl::Span<const int> ints);
+ //
+ // // Okay: the std::initializer_list<int> will reference a temporary array
+ // // that isn't destroyed until after the call to Process returns.
+ // Process({ 17, 19 });
+ //
+ // // Not okay: the storage used by the std::initializer_list<int> is not
+ // // allowed to be referenced after the first line.
+ // absl::Span<const int> ints = { 17, 19 };
+ // Process(ints);
+ //
+ // // Not okay for the same reason as above: even when the elements of the
+ // // initializer list expression are not temporaries the underlying array
+ // // is, so the initializer list must still outlive the span.
+ // const int foo = 17;
+ // absl::Span<const int> ints = { foo };
+ // Process(ints);
+ //
+ template <typename LazyT = T,
+ typename = EnableIfConstView<LazyT>>
+ Span(
+ std::initializer_list<value_type> v) noexcept // NOLINT(runtime/explicit)
+ : Span(v.begin(), v.size()) {}
+
+ // Accessors
+
+ // Span::data()
+ //
+ // Returns a pointer to the span's underlying array of data (which is held
+ // outside the span).
+ constexpr pointer data() const noexcept { return ptr_; }
+
+ // Span::size()
+ //
+ // Returns the size of this span.
+ constexpr size_type size() const noexcept { return len_; }
+
+ // Span::length()
+ //
+ // Returns the length (size) of this span.
+ constexpr size_type length() const noexcept { return size(); }
+
+ // Span::empty()
+ //
+ // Returns a boolean indicating whether or not this span is considered empty.
+ constexpr bool empty() const noexcept { return size() == 0; }
+
+ // Span::operator[]
+ //
+ // Returns a reference to the i'th element of this span.
+ constexpr reference operator[](size_type i) const noexcept {
+ // MSVC 2015 accepts this as constexpr, but not ptr_[i]
+ return *(data() + i);
+ }
+
+ // Span::at()
+ //
+ // Returns a reference to the i'th element of this span.
+ constexpr reference at(size_type i) const {
+ return ABSL_PREDICT_FALSE(i < size())
+ ? ptr_[i]
+ : (base_internal::ThrowStdOutOfRange(
+ "Span::at failed bounds check"),
+ ptr_[i]);
+ }
+
+ // Span::front()
+ //
+ // Returns a reference to the first element of this span.
+ reference front() const noexcept { return ABSL_ASSERT(size() > 0), ptr_[0]; }
+
+ // Span::back()
+ //
+ // Returns a reference to the last element of this span.
+ reference back() const noexcept {
+ return ABSL_ASSERT(size() > 0), ptr_[size() - 1];
+ }
+
+ // Span::begin()
+ //
+ // Returns an iterator to the first element of this span.
+ constexpr iterator begin() const noexcept { return ptr_; }
+
+ // Span::cbegin()
+ //
+ // Returns a const iterator to the first element of this span.
+ constexpr const_iterator cbegin() const noexcept { return ptr_; }
+
+ // Span::end()
+ //
+ // Returns an iterator to the last element of this span.
+ iterator end() const noexcept { return ptr_ + len_; }
+
+ // Span::cend()
+ //
+ // Returns a const iterator to the last element of this span.
+ const_iterator cend() const noexcept { return end(); }
+
+ // Span::rbegin()
+ //
+ // Returns a reverse iterator starting at the last element of this span.
+ reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); }
+
+ // Span::crbegin()
+ //
+ // Returns a reverse const iterator starting at the last element of this span.
+ const_reverse_iterator crbegin() const noexcept { return rbegin(); }
+
+ // Span::rend()
+ //
+ // Returns a reverse iterator starting at the first element of this span.
+ reverse_iterator rend() const noexcept { return reverse_iterator(begin()); }
+
+ // Span::crend()
+ //
+ // Returns a reverse iterator starting at the first element of this span.
+ const_reverse_iterator crend() const noexcept { return rend(); }
+
+ // Span mutations
+
+ // Span::remove_prefix()
+ //
+ // Removes the first `n` elements from the span.
+ void remove_prefix(size_type n) noexcept {
+ assert(len_ >= n);
+ ptr_ += n;
+ len_ -= n;
+ }
+
+ // Span::remove_suffix()
+ //
+ // Removes the last `n` elements from the span.
+ void remove_suffix(size_type n) noexcept {
+ assert(len_ >= n);
+ len_ -= n;
+ }
+
+ // Span::subspan()
+ //
+ // Returns a `Span` starting at element `pos` and of length `len`, with
+ // proper bounds checking to ensure `len` does not exceed the ptr+size of the
+ // original array. (Spans whose `len` would point past the end of the array
+ // will throw a `std::out_of_range`.)
+ constexpr Span subspan(size_type pos = 0, size_type len = npos) const {
+ return (pos <= len_)
+ ? Span(ptr_ + pos, span_internal::Min(len_ - pos, len))
+ : (base_internal::ThrowStdOutOfRange("pos > size()"), Span());
+ }
+
+ private:
+ pointer ptr_;
+ size_type len_;
+};
+
+template <typename T>
+const typename Span<T>::size_type Span<T>::npos;
+
+// Span relationals
+
+// Equality is compared element-by-element, while ordering is lexicographical.
+// We provide three overloads for each operator to cover any combination on the
+// left or right hand side of mutable Span<T>, read-only Span<const T>, and
+// convertible-to-read-only Span<T>.
+// TODO(zhangxy): Due to MSVC overload resolution bug with partial ordering
+// template functions, 5 overloads per operator is needed as a workaround. We
+// should update them to 3 overloads per operator using non-deduced context like
+// string_view, i.e.
+// - (Span<T>, Span<T>)
+// - (Span<T>, non_deduced<Span<const T>>)
+// - (non_deduced<Span<const T>>, Span<T>)
+
+// operator==
+template <typename T>
+bool operator==(Span<T> a, Span<T> b) {
+ return span_internal::EqualImpl<const T>(a, b);
+}
+template <typename T>
+bool operator==(Span<const T> a, Span<T> b) {
+ return span_internal::EqualImpl<const T>(a, b);
+}
+template <typename T>
+bool operator==(Span<T> a, Span<const T> b) {
+ return span_internal::EqualImpl<const T>(a, b);
+}
+template <typename T, typename U,
+ typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+bool operator==(const U& a, Span<T> b) {
+ return span_internal::EqualImpl<const T>(a, b);
+}
+template <typename T, typename U,
+ typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+bool operator==(Span<T> a, const U& b) {
+ return span_internal::EqualImpl<const T>(a, b);
+}
+
+// operator!=
+template <typename T>
+bool operator!=(Span<T> a, Span<T> b) {
+ return !(a == b);
+}
+template <typename T>
+bool operator!=(Span<const T> a, Span<T> b) {
+ return !(a == b);
+}
+template <typename T>
+bool operator!=(Span<T> a, Span<const T> b) {
+ return !(a == b);
+}
+template <typename T, typename U,
+ typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+bool operator!=(const U& a, Span<T> b) {
+ return !(a == b);
+}
+template <typename T, typename U,
+ typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+bool operator!=(Span<T> a, const U& b) {
+ return !(a == b);
+}
+
+// operator<
+template <typename T>
+bool operator<(Span<T> a, Span<T> b) {
+ return span_internal::LessThanImpl<const T>(a, b);
+}
+template <typename T>
+bool operator<(Span<const T> a, Span<T> b) {
+ return span_internal::LessThanImpl<const T>(a, b);
+}
+template <typename T>
+bool operator<(Span<T> a, Span<const T> b) {
+ return span_internal::LessThanImpl<const T>(a, b);
+}
+template <typename T, typename U,
+ typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+bool operator<(const U& a, Span<T> b) {
+ return span_internal::LessThanImpl<const T>(a, b);
+}
+template <typename T, typename U,
+ typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+bool operator<(Span<T> a, const U& b) {
+ return span_internal::LessThanImpl<const T>(a, b);
+}
+
+// operator>
+template <typename T>
+bool operator>(Span<T> a, Span<T> b) {
+ return b < a;
+}
+template <typename T>
+bool operator>(Span<const T> a, Span<T> b) {
+ return b < a;
+}
+template <typename T>
+bool operator>(Span<T> a, Span<const T> b) {
+ return b < a;
+}
+template <typename T, typename U,
+ typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+bool operator>(const U& a, Span<T> b) {
+ return b < a;
+}
+template <typename T, typename U,
+ typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+bool operator>(Span<T> a, const U& b) {
+ return b < a;
+}
+
+// operator<=
+template <typename T>
+bool operator<=(Span<T> a, Span<T> b) {
+ return !(b < a);
+}
+template <typename T>
+bool operator<=(Span<const T> a, Span<T> b) {
+ return !(b < a);
+}
+template <typename T>
+bool operator<=(Span<T> a, Span<const T> b) {
+ return !(b < a);
+}
+template <typename T, typename U,
+ typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+bool operator<=(const U& a, Span<T> b) {
+ return !(b < a);
+}
+template <typename T, typename U,
+ typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+bool operator<=(Span<T> a, const U& b) {
+ return !(b < a);
+}
+
+// operator>=
+template <typename T>
+bool operator>=(Span<T> a, Span<T> b) {
+ return !(a < b);
+}
+template <typename T>
+bool operator>=(Span<const T> a, Span<T> b) {
+ return !(a < b);
+}
+template <typename T>
+bool operator>=(Span<T> a, Span<const T> b) {
+ return !(a < b);
+}
+template <typename T, typename U,
+ typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+bool operator>=(const U& a, Span<T> b) {
+ return !(a < b);
+}
+template <typename T, typename U,
+ typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+bool operator>=(Span<T> a, const U& b) {
+ return !(a < b);
+}
+
+// MakeSpan()
+//
+// Constructs a mutable `Span<T>`, deducing `T` automatically from either a
+// container or pointer+size.
+//
+// Because a read-only `Span<const T>` is implicitly constructed from container
+// types regardless of whether the container itself is a const container,
+// constructing mutable spans of type `Span<T>` from containers requires
+// explicit constructors. The container-accepting version of `MakeSpan()`
+// deduces the type of `T` by the constness of the pointer received from the
+// container's `data()` member. Similarly, the pointer-accepting version returns
+// a `Span<const T>` if `T` is `const`, and a `Span<T>` otherwise.
+//
+// Examples:
+//
+// void MyRoutine(absl::Span<MyComplicatedType> a) {
+// ...
+// };
+// // my_vector is a container of non-const types
+// std::vector<MyComplicatedType> my_vector;
+//
+// // Constructing a Span implicitly attempts to create a Span of type
+// // `Span<const T>`
+// MyRoutine(my_vector); // error, type mismatch
+//
+// // Explicitly constructing the Span is verbose
+// MyRoutine(absl::Span<MyComplicatedType>(my_vector);
+//
+// // Use MakeSpan() to make an absl::Span<T>
+// MyRoutine(absl::MakeSpan(my_vector));
+//
+// // Construct a span from an array ptr+size
+// absl::Span<T> my_span() {
+// return absl::MakeSpan(&array[0], num_elements_);
+// }
+//
+template <int&... ExplicitArgumentBarrier, typename T>
+constexpr Span<T> MakeSpan(T* ptr, size_t size) noexcept {
+ return Span<T>(ptr, size);
+}
+
+template <int&... ExplicitArgumentBarrier, typename T>
+Span<T> MakeSpan(T* begin, T* end) noexcept {
+ return ABSL_ASSERT(begin <= end), Span<T>(begin, end - begin);
+}
+
+template <int&... ExplicitArgumentBarrier, typename C>
+constexpr auto MakeSpan(C& c) noexcept // NOLINT(runtime/references)
+ -> decltype(absl::MakeSpan(span_internal::GetData(c), c.size())) {
+ return MakeSpan(span_internal::GetData(c), c.size());
+}
+
+template <int&... ExplicitArgumentBarrier, typename T, size_t N>
+constexpr Span<T> MakeSpan(T (&array)[N]) noexcept {
+ return Span<T>(array, N);
+}
+
+// MakeConstSpan()
+//
+// Constructs a `Span<const T>` as with `MakeSpan`, deducing `T` automatically,
+// but always returning a `Span<const T>`.
+//
+// Examples:
+//
+// void ProcessInts(absl::Span<const int> some_ints);
+//
+// // Call with a pointer and size.
+// int array[3] = { 0, 0, 0 };
+// ProcessInts(absl::MakeConstSpan(&array[0], 3));
+//
+// // Call with a [begin, end) pair.
+// ProcessInts(absl::MakeConstSpan(&array[0], &array[3]));
+//
+// // Call directly with an array.
+// ProcessInts(absl::MakeConstSpan(array));
+//
+// // Call with a contiguous container.
+// std::vector<int> some_ints = ...;
+// ProcessInts(absl::MakeConstSpan(some_ints));
+// ProcessInts(absl::MakeConstSpan(std::vector<int>{ 0, 0, 0 }));
+//
+template <int&... ExplicitArgumentBarrier, typename T>
+constexpr Span<const T> MakeConstSpan(T* ptr, size_t size) noexcept {
+ return Span<const T>(ptr, size);
+}
+
+template <int&... ExplicitArgumentBarrier, typename T>
+Span<const T> MakeConstSpan(T* begin, T* end) noexcept {
+ return ABSL_ASSERT(begin <= end), Span<const T>(begin, end - begin);
+}
+
+template <int&... ExplicitArgumentBarrier, typename C>
+constexpr auto MakeConstSpan(const C& c) noexcept -> decltype(MakeSpan(c)) {
+ return MakeSpan(c);
+}
+
+template <int&... ExplicitArgumentBarrier, typename T, size_t N>
+constexpr Span<const T> MakeConstSpan(const T (&array)[N]) noexcept {
+ return Span<const T>(array, N);
+}
+} // namespace absl
+#endif // ABSL_TYPES_SPAN_H_