|
|
|||
File indexing completed on 2025-12-15 09:41:58
0001 // 0002 // Copyright 2017 The Abseil Authors. 0003 // 0004 // Licensed under the Apache License, Version 2.0 (the "License"); 0005 // you may not use this file except in compliance with the License. 0006 // You may obtain a copy of the License at 0007 // 0008 // https://www.apache.org/licenses/LICENSE-2.0 0009 // 0010 // Unless required by applicable law or agreed to in writing, software 0011 // distributed under the License is distributed on an "AS IS" BASIS, 0012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 0013 // See the License for the specific language governing permissions and 0014 // limitations under the License. 0015 // 0016 // ----------------------------------------------------------------------------- 0017 // span.h 0018 // ----------------------------------------------------------------------------- 0019 // 0020 // This header file defines a `Span<T>` type for holding a reference to existing 0021 // array data. The `Span` object, much like the `absl::string_view` object, 0022 // does not own such data itself, and the data being referenced by the span must 0023 // outlive the span itself. Unlike `view` type references, a span can hold a 0024 // reference to mutable data (and can mutate it for underlying types of 0025 // non-const T.) A span provides a lightweight way to pass a reference to such 0026 // data. 0027 // 0028 // Additionally, this header file defines `MakeSpan()` and `MakeConstSpan()` 0029 // factory functions, for clearly creating spans of type `Span<T>` or read-only 0030 // `Span<const T>` when such types may be difficult to identify due to issues 0031 // with implicit conversion. 0032 // 0033 // The C++20 draft standard includes a `std::span` type. As of June 2020, the 0034 // differences between `absl::Span` and `std::span` are: 0035 // * `absl::Span` has `operator==` (which is likely a design bug, 0036 // per https://abseil.io/blog/20180531-regular-types) 0037 // * `absl::Span` has the factory functions `MakeSpan()` and 0038 // `MakeConstSpan()` 0039 // * bounds-checked access to `absl::Span` is accomplished with `at()` 0040 // * `absl::Span` has compiler-provided move and copy constructors and 0041 // assignment. This is due to them being specified as `constexpr`, but that 0042 // implies const in C++11. 0043 // * A read-only `absl::Span<const T>` can be implicitly constructed from an 0044 // initializer list. 0045 // * `absl::Span` has no `bytes()`, `size_bytes()`, `as_bytes()`, or 0046 // `as_writable_bytes()` methods 0047 // * `absl::Span` has no static extent template parameter, nor constructors 0048 // which exist only because of the static extent parameter. 0049 // * `absl::Span` has an explicit mutable-reference constructor 0050 // 0051 // For more information, see the class comments below. 0052 #ifndef ABSL_TYPES_SPAN_H_ 0053 #define ABSL_TYPES_SPAN_H_ 0054 0055 #include <algorithm> 0056 #include <cassert> 0057 #include <cstddef> 0058 #include <initializer_list> 0059 #include <iterator> 0060 #include <type_traits> 0061 #include <utility> 0062 0063 #include "absl/base/attributes.h" 0064 #include "absl/base/internal/throw_delegate.h" 0065 #include "absl/base/macros.h" 0066 #include "absl/base/nullability.h" 0067 #include "absl/base/optimization.h" 0068 #include "absl/base/port.h" // TODO(strel): remove this include 0069 #include "absl/meta/type_traits.h" 0070 #include "absl/types/internal/span.h" 0071 0072 namespace absl { 0073 ABSL_NAMESPACE_BEGIN 0074 0075 //------------------------------------------------------------------------------ 0076 // Span 0077 //------------------------------------------------------------------------------ 0078 // 0079 // A `Span` is an "array reference" type for holding a reference of contiguous 0080 // array data; the `Span` object does not and cannot own such data itself. A 0081 // span provides an easy way to provide overloads for anything operating on 0082 // contiguous sequences without needing to manage pointers and array lengths 0083 // manually. 0084 0085 // A span is conceptually a pointer (ptr) and a length (size) into an already 0086 // existing array of contiguous memory; the array it represents references the 0087 // elements "ptr[0] .. ptr[size-1]". Passing a properly-constructed `Span` 0088 // instead of raw pointers avoids many issues related to index out of bounds 0089 // errors. 0090 // 0091 // Spans may also be constructed from containers holding contiguous sequences. 0092 // Such containers must supply `data()` and `size() const` methods (e.g 0093 // `std::vector<T>`, `absl::InlinedVector<T, N>`). All implicit conversions to 0094 // `absl::Span` from such containers will create spans of type `const T`; 0095 // spans which can mutate their values (of type `T`) must use explicit 0096 // constructors. 0097 // 0098 // A `Span<T>` is somewhat analogous to an `absl::string_view`, but for an array 0099 // of elements of type `T`, and unlike an `absl::string_view`, a span can hold a 0100 // reference to mutable data. A user of `Span` must ensure that the data being 0101 // pointed to outlives the `Span` itself. 0102 // 0103 // You can construct a `Span<T>` in several ways: 0104 // 0105 // * Explicitly from a reference to a container type 0106 // * Explicitly from a pointer and size 0107 // * Implicitly from a container type (but only for spans of type `const T`) 0108 // * Using the `MakeSpan()` or `MakeConstSpan()` factory functions. 0109 // 0110 // Examples: 0111 // 0112 // // Construct a Span explicitly from a container: 0113 // std::vector<int> v = {1, 2, 3, 4, 5}; 0114 // auto span = absl::Span<const int>(v); 0115 // 0116 // // Construct a Span explicitly from a C-style array: 0117 // int a[5] = {1, 2, 3, 4, 5}; 0118 // auto span = absl::Span<const int>(a); 0119 // 0120 // // Construct a Span implicitly from a container 0121 // void MyRoutine(absl::Span<const int> a) { 0122 // ... 0123 // } 0124 // std::vector v = {1,2,3,4,5}; 0125 // MyRoutine(v) // convert to Span<const T> 0126 // 0127 // Note that `Span` objects, in addition to requiring that the memory they 0128 // point to remains alive, must also ensure that such memory does not get 0129 // reallocated. Therefore, to avoid undefined behavior, containers with 0130 // associated spans should not invoke operations that may reallocate memory 0131 // (such as resizing) or invalidate iterators into the container. 0132 // 0133 // One common use for a `Span` is when passing arguments to a routine that can 0134 // accept a variety of array types (e.g. a `std::vector`, `absl::InlinedVector`, 0135 // a C-style array, etc.). Instead of creating overloads for each case, you 0136 // can simply specify a `Span` as the argument to such a routine. 0137 // 0138 // Example: 0139 // 0140 // void MyRoutine(absl::Span<const int> a) { 0141 // ... 0142 // } 0143 // 0144 // std::vector v = {1,2,3,4,5}; 0145 // MyRoutine(v); 0146 // 0147 // absl::InlinedVector<int, 4> my_inline_vector; 0148 // MyRoutine(my_inline_vector); 0149 // 0150 // // Explicit constructor from pointer,size 0151 // int* my_array = new int[10]; 0152 // MyRoutine(absl::Span<const int>(my_array, 10)); 0153 template <typename T> 0154 class ABSL_INTERNAL_ATTRIBUTE_VIEW Span { 0155 private: 0156 // Used to determine whether a Span can be constructed from a container of 0157 // type C. 0158 template <typename C> 0159 using EnableIfConvertibleFrom = 0160 typename std::enable_if<span_internal::HasData<T, C>::value && 0161 span_internal::HasSize<C>::value>::type; 0162 0163 // Used to SFINAE-enable a function when the slice elements are const. 0164 template <typename U> 0165 using EnableIfValueIsConst = 0166 typename std::enable_if<std::is_const<T>::value, U>::type; 0167 0168 // Used to SFINAE-enable a function when the slice elements are mutable. 0169 template <typename U> 0170 using EnableIfValueIsMutable = 0171 typename std::enable_if<!std::is_const<T>::value, U>::type; 0172 0173 public: 0174 using element_type = T; 0175 using value_type = absl::remove_cv_t<T>; 0176 // TODO(b/316099902) - pointer should be Nullable<T*>, but this makes it hard 0177 // to recognize foreach loops as safe. 0178 using pointer = T*; 0179 using const_pointer = const T*; 0180 using reference = T&; 0181 using const_reference = const T&; 0182 using iterator = pointer; 0183 using const_iterator = const_pointer; 0184 using reverse_iterator = std::reverse_iterator<iterator>; 0185 using const_reverse_iterator = std::reverse_iterator<const_iterator>; 0186 using size_type = size_t; 0187 using difference_type = ptrdiff_t; 0188 using absl_internal_is_view = std::true_type; 0189 0190 static const size_type npos = ~(size_type(0)); 0191 0192 constexpr Span() noexcept : Span(nullptr, 0) {} 0193 constexpr Span(pointer array, size_type length) noexcept 0194 : ptr_(array), len_(length) {} 0195 0196 // Implicit conversion constructors 0197 template <size_t N> 0198 constexpr Span(T (&a)[N]) noexcept // NOLINT(runtime/explicit) 0199 : Span(a, N) {} 0200 0201 // Explicit reference constructor for a mutable `Span<T>` type. Can be 0202 // replaced with MakeSpan() to infer the type parameter. 0203 template <typename V, typename = EnableIfConvertibleFrom<V>, 0204 typename = EnableIfValueIsMutable<V>, 0205 typename = span_internal::EnableIfNotIsView<V>> 0206 explicit Span( 0207 V& v 0208 ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept // NOLINT(runtime/references) 0209 : Span(span_internal::GetData(v), v.size()) {} 0210 0211 // Implicit reference constructor for a read-only `Span<const T>` type 0212 template <typename V, typename = EnableIfConvertibleFrom<V>, 0213 typename = EnableIfValueIsConst<V>, 0214 typename = span_internal::EnableIfNotIsView<V>> 0215 constexpr Span( 0216 const V& v 0217 ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept // NOLINT(runtime/explicit) 0218 : Span(span_internal::GetData(v), v.size()) {} 0219 0220 // Overloads of the above two functions that are only enabled for view types. 0221 // This is so we can drop the ABSL_ATTRIBUTE_LIFETIME_BOUND annotation. These 0222 // overloads must be made unique by using a different template parameter list 0223 // (hence the = 0 for the IsView enabler). 0224 template <typename V, typename = EnableIfConvertibleFrom<V>, 0225 typename = EnableIfValueIsMutable<V>, 0226 span_internal::EnableIfIsView<V> = 0> 0227 explicit Span(V& v) noexcept // NOLINT(runtime/references) 0228 : Span(span_internal::GetData(v), v.size()) {} 0229 template <typename V, typename = EnableIfConvertibleFrom<V>, 0230 typename = EnableIfValueIsConst<V>, 0231 span_internal::EnableIfIsView<V> = 0> 0232 constexpr Span(const V& v) noexcept // NOLINT(runtime/explicit) 0233 : Span(span_internal::GetData(v), v.size()) {} 0234 0235 // Implicit constructor from an initializer list, making it possible to pass a 0236 // brace-enclosed initializer list to a function expecting a `Span`. Such 0237 // spans constructed from an initializer list must be of type `Span<const T>`. 0238 // 0239 // void Process(absl::Span<const int> x); 0240 // Process({1, 2, 3}); 0241 // 0242 // Note that as always the array referenced by the span must outlive the span. 0243 // Since an initializer list constructor acts as if it is fed a temporary 0244 // array (cf. C++ standard [dcl.init.list]/5), it's safe to use this 0245 // constructor only when the `std::initializer_list` itself outlives the span. 0246 // In order to meet this requirement it's sufficient to ensure that neither 0247 // the span nor a copy of it is used outside of the expression in which it's 0248 // created: 0249 // 0250 // // Assume that this function uses the array directly, not retaining any 0251 // // copy of the span or pointer to any of its elements. 0252 // void Process(absl::Span<const int> ints); 0253 // 0254 // // Okay: the std::initializer_list<int> will reference a temporary array 0255 // // that isn't destroyed until after the call to Process returns. 0256 // Process({ 17, 19 }); 0257 // 0258 // // Not okay: the storage used by the std::initializer_list<int> is not 0259 // // allowed to be referenced after the first line. 0260 // absl::Span<const int> ints = { 17, 19 }; 0261 // Process(ints); 0262 // 0263 // // Not okay for the same reason as above: even when the elements of the 0264 // // initializer list expression are not temporaries the underlying array 0265 // // is, so the initializer list must still outlive the span. 0266 // const int foo = 17; 0267 // absl::Span<const int> ints = { foo }; 0268 // Process(ints); 0269 // 0270 template <typename LazyT = T, 0271 typename = EnableIfValueIsConst<LazyT>> 0272 Span(std::initializer_list<value_type> v 0273 ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept // NOLINT(runtime/explicit) 0274 : Span(v.begin(), v.size()) {} 0275 0276 // Accessors 0277 0278 // Span::data() 0279 // 0280 // Returns a pointer to the span's underlying array of data (which is held 0281 // outside the span). 0282 constexpr pointer data() const noexcept { return ptr_; } 0283 0284 // Span::size() 0285 // 0286 // Returns the size of this span. 0287 constexpr size_type size() const noexcept { return len_; } 0288 0289 // Span::length() 0290 // 0291 // Returns the length (size) of this span. 0292 constexpr size_type length() const noexcept { return size(); } 0293 0294 // Span::empty() 0295 // 0296 // Returns a boolean indicating whether or not this span is considered empty. 0297 constexpr bool empty() const noexcept { return size() == 0; } 0298 0299 // Span::operator[] 0300 // 0301 // Returns a reference to the i'th element of this span. 0302 constexpr reference operator[](size_type i) const noexcept { 0303 return ABSL_HARDENING_ASSERT(i < size()), ptr_[i]; 0304 } 0305 0306 // Span::at() 0307 // 0308 // Returns a reference to the i'th element of this span. 0309 constexpr reference at(size_type i) const { 0310 return ABSL_PREDICT_TRUE(i < size()) // 0311 ? *(data() + i) 0312 : (base_internal::ThrowStdOutOfRange( 0313 "Span::at failed bounds check"), 0314 *(data() + i)); 0315 } 0316 0317 // Span::front() 0318 // 0319 // Returns a reference to the first element of this span. The span must not 0320 // be empty. 0321 constexpr reference front() const noexcept { 0322 return ABSL_HARDENING_ASSERT(size() > 0), *data(); 0323 } 0324 0325 // Span::back() 0326 // 0327 // Returns a reference to the last element of this span. The span must not 0328 // be empty. 0329 constexpr reference back() const noexcept { 0330 return ABSL_HARDENING_ASSERT(size() > 0), *(data() + size() - 1); 0331 } 0332 0333 // Span::begin() 0334 // 0335 // Returns an iterator pointing to the first element of this span, or `end()` 0336 // if the span is empty. 0337 constexpr iterator begin() const noexcept { return data(); } 0338 0339 // Span::cbegin() 0340 // 0341 // Returns a const iterator pointing to the first element of this span, or 0342 // `end()` if the span is empty. 0343 constexpr const_iterator cbegin() const noexcept { return begin(); } 0344 0345 // Span::end() 0346 // 0347 // Returns an iterator pointing just beyond the last element at the 0348 // end of this span. This iterator acts as a placeholder; attempting to 0349 // access it results in undefined behavior. 0350 constexpr iterator end() const noexcept { return data() + size(); } 0351 0352 // Span::cend() 0353 // 0354 // Returns a const iterator pointing just beyond the last element at the 0355 // end of this span. This iterator acts as a placeholder; attempting to 0356 // access it results in undefined behavior. 0357 constexpr const_iterator cend() const noexcept { return end(); } 0358 0359 // Span::rbegin() 0360 // 0361 // Returns a reverse iterator pointing to the last element at the end of this 0362 // span, or `rend()` if the span is empty. 0363 constexpr reverse_iterator rbegin() const noexcept { 0364 return reverse_iterator(end()); 0365 } 0366 0367 // Span::crbegin() 0368 // 0369 // Returns a const reverse iterator pointing to the last element at the end of 0370 // this span, or `crend()` if the span is empty. 0371 constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); } 0372 0373 // Span::rend() 0374 // 0375 // Returns a reverse iterator pointing just before the first element 0376 // at the beginning of this span. This pointer acts as a placeholder; 0377 // attempting to access its element results in undefined behavior. 0378 constexpr reverse_iterator rend() const noexcept { 0379 return reverse_iterator(begin()); 0380 } 0381 0382 // Span::crend() 0383 // 0384 // Returns a reverse const iterator pointing just before the first element 0385 // at the beginning of this span. This pointer acts as a placeholder; 0386 // attempting to access its element results in undefined behavior. 0387 constexpr const_reverse_iterator crend() const noexcept { return rend(); } 0388 0389 // Span mutations 0390 0391 // Span::remove_prefix() 0392 // 0393 // Removes the first `n` elements from the span. 0394 void remove_prefix(size_type n) noexcept { 0395 ABSL_HARDENING_ASSERT(size() >= n); 0396 ptr_ += n; 0397 len_ -= n; 0398 } 0399 0400 // Span::remove_suffix() 0401 // 0402 // Removes the last `n` elements from the span. 0403 void remove_suffix(size_type n) noexcept { 0404 ABSL_HARDENING_ASSERT(size() >= n); 0405 len_ -= n; 0406 } 0407 0408 // Span::subspan() 0409 // 0410 // Returns a `Span` starting at element `pos` and of length `len`. Both `pos` 0411 // and `len` are of type `size_type` and thus non-negative. Parameter `pos` 0412 // must be <= size(). Any `len` value that points past the end of the span 0413 // will be trimmed to at most size() - `pos`. A default `len` value of `npos` 0414 // ensures the returned subspan continues until the end of the span. 0415 // 0416 // Examples: 0417 // 0418 // std::vector<int> vec = {10, 11, 12, 13}; 0419 // absl::MakeSpan(vec).subspan(1, 2); // {11, 12} 0420 // absl::MakeSpan(vec).subspan(2, 8); // {12, 13} 0421 // absl::MakeSpan(vec).subspan(1); // {11, 12, 13} 0422 // absl::MakeSpan(vec).subspan(4); // {} 0423 // absl::MakeSpan(vec).subspan(5); // throws std::out_of_range 0424 constexpr Span subspan(size_type pos = 0, size_type len = npos) const { 0425 return (pos <= size()) 0426 ? Span(data() + pos, (std::min)(size() - pos, len)) 0427 : (base_internal::ThrowStdOutOfRange("pos > size()"), Span()); 0428 } 0429 0430 // Span::first() 0431 // 0432 // Returns a `Span` containing first `len` elements. Parameter `len` is of 0433 // type `size_type` and thus non-negative. `len` value must be <= size(). 0434 // 0435 // Examples: 0436 // 0437 // std::vector<int> vec = {10, 11, 12, 13}; 0438 // absl::MakeSpan(vec).first(1); // {10} 0439 // absl::MakeSpan(vec).first(3); // {10, 11, 12} 0440 // absl::MakeSpan(vec).first(5); // throws std::out_of_range 0441 constexpr Span first(size_type len) const { 0442 return (len <= size()) 0443 ? Span(data(), len) 0444 : (base_internal::ThrowStdOutOfRange("len > size()"), Span()); 0445 } 0446 0447 // Span::last() 0448 // 0449 // Returns a `Span` containing last `len` elements. Parameter `len` is of 0450 // type `size_type` and thus non-negative. `len` value must be <= size(). 0451 // 0452 // Examples: 0453 // 0454 // std::vector<int> vec = {10, 11, 12, 13}; 0455 // absl::MakeSpan(vec).last(1); // {13} 0456 // absl::MakeSpan(vec).last(3); // {11, 12, 13} 0457 // absl::MakeSpan(vec).last(5); // throws std::out_of_range 0458 constexpr Span last(size_type len) const { 0459 return (len <= size()) 0460 ? Span(size() - len + data(), len) 0461 : (base_internal::ThrowStdOutOfRange("len > size()"), Span()); 0462 } 0463 0464 // Support for absl::Hash. 0465 template <typename H> 0466 friend H AbslHashValue(H h, Span v) { 0467 return H::combine(H::combine_contiguous(std::move(h), v.data(), v.size()), 0468 v.size()); 0469 } 0470 0471 private: 0472 pointer ptr_; 0473 size_type len_; 0474 }; 0475 0476 template <typename T> 0477 const typename Span<T>::size_type Span<T>::npos; 0478 0479 // Span relationals 0480 0481 // Equality is compared element-by-element, while ordering is lexicographical. 0482 // We provide three overloads for each operator to cover any combination on the 0483 // left or right hand side of mutable Span<T>, read-only Span<const T>, and 0484 // convertible-to-read-only Span<T>. 0485 // TODO(zhangxy): Due to MSVC overload resolution bug with partial ordering 0486 // template functions, 5 overloads per operator is needed as a workaround. We 0487 // should update them to 3 overloads per operator using non-deduced context like 0488 // string_view, i.e. 0489 // - (Span<T>, Span<T>) 0490 // - (Span<T>, non_deduced<Span<const T>>) 0491 // - (non_deduced<Span<const T>>, Span<T>) 0492 0493 // operator== 0494 template <typename T> 0495 bool operator==(Span<T> a, Span<T> b) { 0496 return span_internal::EqualImpl<Span, const T>(a, b); 0497 } 0498 template <typename T> 0499 bool operator==(Span<const T> a, Span<T> b) { 0500 return span_internal::EqualImpl<Span, const T>(a, b); 0501 } 0502 template <typename T> 0503 bool operator==(Span<T> a, Span<const T> b) { 0504 return span_internal::EqualImpl<Span, const T>(a, b); 0505 } 0506 template < 0507 typename T, typename U, 0508 typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> 0509 bool operator==(const U& a, Span<T> b) { 0510 return span_internal::EqualImpl<Span, const T>(a, b); 0511 } 0512 template < 0513 typename T, typename U, 0514 typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> 0515 bool operator==(Span<T> a, const U& b) { 0516 return span_internal::EqualImpl<Span, const T>(a, b); 0517 } 0518 0519 // operator!= 0520 template <typename T> 0521 bool operator!=(Span<T> a, Span<T> b) { 0522 return !(a == b); 0523 } 0524 template <typename T> 0525 bool operator!=(Span<const T> a, Span<T> b) { 0526 return !(a == b); 0527 } 0528 template <typename T> 0529 bool operator!=(Span<T> a, Span<const T> b) { 0530 return !(a == b); 0531 } 0532 template < 0533 typename T, typename U, 0534 typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> 0535 bool operator!=(const U& a, Span<T> b) { 0536 return !(a == b); 0537 } 0538 template < 0539 typename T, typename U, 0540 typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> 0541 bool operator!=(Span<T> a, const U& b) { 0542 return !(a == b); 0543 } 0544 0545 // operator< 0546 template <typename T> 0547 bool operator<(Span<T> a, Span<T> b) { 0548 return span_internal::LessThanImpl<Span, const T>(a, b); 0549 } 0550 template <typename T> 0551 bool operator<(Span<const T> a, Span<T> b) { 0552 return span_internal::LessThanImpl<Span, const T>(a, b); 0553 } 0554 template <typename T> 0555 bool operator<(Span<T> a, Span<const T> b) { 0556 return span_internal::LessThanImpl<Span, const T>(a, b); 0557 } 0558 template < 0559 typename T, typename U, 0560 typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> 0561 bool operator<(const U& a, Span<T> b) { 0562 return span_internal::LessThanImpl<Span, const T>(a, b); 0563 } 0564 template < 0565 typename T, typename U, 0566 typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> 0567 bool operator<(Span<T> a, const U& b) { 0568 return span_internal::LessThanImpl<Span, const T>(a, b); 0569 } 0570 0571 // operator> 0572 template <typename T> 0573 bool operator>(Span<T> a, Span<T> b) { 0574 return b < a; 0575 } 0576 template <typename T> 0577 bool operator>(Span<const T> a, Span<T> b) { 0578 return b < a; 0579 } 0580 template <typename T> 0581 bool operator>(Span<T> a, Span<const T> b) { 0582 return b < a; 0583 } 0584 template < 0585 typename T, typename U, 0586 typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> 0587 bool operator>(const U& a, Span<T> b) { 0588 return b < a; 0589 } 0590 template < 0591 typename T, typename U, 0592 typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> 0593 bool operator>(Span<T> a, const U& b) { 0594 return b < a; 0595 } 0596 0597 // operator<= 0598 template <typename T> 0599 bool operator<=(Span<T> a, Span<T> b) { 0600 return !(b < a); 0601 } 0602 template <typename T> 0603 bool operator<=(Span<const T> a, Span<T> b) { 0604 return !(b < a); 0605 } 0606 template <typename T> 0607 bool operator<=(Span<T> a, Span<const T> b) { 0608 return !(b < a); 0609 } 0610 template < 0611 typename T, typename U, 0612 typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> 0613 bool operator<=(const U& a, Span<T> b) { 0614 return !(b < a); 0615 } 0616 template < 0617 typename T, typename U, 0618 typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> 0619 bool operator<=(Span<T> a, const U& b) { 0620 return !(b < a); 0621 } 0622 0623 // operator>= 0624 template <typename T> 0625 bool operator>=(Span<T> a, Span<T> b) { 0626 return !(a < b); 0627 } 0628 template <typename T> 0629 bool operator>=(Span<const T> a, Span<T> b) { 0630 return !(a < b); 0631 } 0632 template <typename T> 0633 bool operator>=(Span<T> a, Span<const T> b) { 0634 return !(a < b); 0635 } 0636 template < 0637 typename T, typename U, 0638 typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> 0639 bool operator>=(const U& a, Span<T> b) { 0640 return !(a < b); 0641 } 0642 template < 0643 typename T, typename U, 0644 typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> 0645 bool operator>=(Span<T> a, const U& b) { 0646 return !(a < b); 0647 } 0648 0649 // MakeSpan() 0650 // 0651 // Constructs a mutable `Span<T>`, deducing `T` automatically from either a 0652 // container or pointer+size. 0653 // 0654 // Because a read-only `Span<const T>` is implicitly constructed from container 0655 // types regardless of whether the container itself is a const container, 0656 // constructing mutable spans of type `Span<T>` from containers requires 0657 // explicit constructors. The container-accepting version of `MakeSpan()` 0658 // deduces the type of `T` by the constness of the pointer received from the 0659 // container's `data()` member. Similarly, the pointer-accepting version returns 0660 // a `Span<const T>` if `T` is `const`, and a `Span<T>` otherwise. 0661 // 0662 // Examples: 0663 // 0664 // void MyRoutine(absl::Span<MyComplicatedType> a) { 0665 // ... 0666 // }; 0667 // // my_vector is a container of non-const types 0668 // std::vector<MyComplicatedType> my_vector; 0669 // 0670 // // Constructing a Span implicitly attempts to create a Span of type 0671 // // `Span<const T>` 0672 // MyRoutine(my_vector); // error, type mismatch 0673 // 0674 // // Explicitly constructing the Span is verbose 0675 // MyRoutine(absl::Span<MyComplicatedType>(my_vector)); 0676 // 0677 // // Use MakeSpan() to make an absl::Span<T> 0678 // MyRoutine(absl::MakeSpan(my_vector)); 0679 // 0680 // // Construct a span from an array ptr+size 0681 // absl::Span<T> my_span() { 0682 // return absl::MakeSpan(&array[0], num_elements_); 0683 // } 0684 // 0685 template <int&... ExplicitArgumentBarrier, typename T> 0686 constexpr Span<T> MakeSpan(absl::Nullable<T*> ptr, size_t size) noexcept { 0687 return Span<T>(ptr, size); 0688 } 0689 0690 template <int&... ExplicitArgumentBarrier, typename T> 0691 Span<T> MakeSpan(absl::Nullable<T*> begin, absl::Nullable<T*> end) noexcept { 0692 return ABSL_HARDENING_ASSERT(begin <= end), 0693 Span<T>(begin, static_cast<size_t>(end - begin)); 0694 } 0695 0696 template <int&... ExplicitArgumentBarrier, typename C> 0697 constexpr auto MakeSpan(C& c) noexcept // NOLINT(runtime/references) 0698 -> decltype(absl::MakeSpan(span_internal::GetData(c), c.size())) { 0699 return MakeSpan(span_internal::GetData(c), c.size()); 0700 } 0701 0702 template <int&... ExplicitArgumentBarrier, typename T, size_t N> 0703 constexpr Span<T> MakeSpan(T (&array)[N]) noexcept { 0704 return Span<T>(array, N); 0705 } 0706 0707 // MakeConstSpan() 0708 // 0709 // Constructs a `Span<const T>` as with `MakeSpan`, deducing `T` automatically, 0710 // but always returning a `Span<const T>`. 0711 // 0712 // Examples: 0713 // 0714 // void ProcessInts(absl::Span<const int> some_ints); 0715 // 0716 // // Call with a pointer and size. 0717 // int array[3] = { 0, 0, 0 }; 0718 // ProcessInts(absl::MakeConstSpan(&array[0], 3)); 0719 // 0720 // // Call with a [begin, end) pair. 0721 // ProcessInts(absl::MakeConstSpan(&array[0], &array[3])); 0722 // 0723 // // Call directly with an array. 0724 // ProcessInts(absl::MakeConstSpan(array)); 0725 // 0726 // // Call with a contiguous container. 0727 // std::vector<int> some_ints = ...; 0728 // ProcessInts(absl::MakeConstSpan(some_ints)); 0729 // ProcessInts(absl::MakeConstSpan(std::vector<int>{ 0, 0, 0 })); 0730 // 0731 template <int&... ExplicitArgumentBarrier, typename T> 0732 constexpr Span<const T> MakeConstSpan(absl::Nullable<T*> ptr, 0733 size_t size) noexcept { 0734 return Span<const T>(ptr, size); 0735 } 0736 0737 template <int&... ExplicitArgumentBarrier, typename T> 0738 Span<const T> MakeConstSpan(absl::Nullable<T*> begin, 0739 absl::Nullable<T*> end) noexcept { 0740 return ABSL_HARDENING_ASSERT(begin <= end), Span<const T>(begin, end - begin); 0741 } 0742 0743 template <int&... ExplicitArgumentBarrier, typename C> 0744 constexpr auto MakeConstSpan(const C& c) noexcept -> decltype(MakeSpan(c)) { 0745 return MakeSpan(c); 0746 } 0747 0748 template <int&... ExplicitArgumentBarrier, typename T, size_t N> 0749 constexpr Span<const T> MakeConstSpan(const T (&array)[N]) noexcept { 0750 return Span<const T>(array, N); 0751 } 0752 ABSL_NAMESPACE_END 0753 } // namespace absl 0754 #endif // ABSL_TYPES_SPAN_H_
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|