|  | // Copyright 2020 The Chromium Authors | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef BASE_CONTAINERS_CONTIGUOUS_ITERATOR_H_ | 
|  | #define BASE_CONTAINERS_CONTIGUOUS_ITERATOR_H_ | 
|  |  | 
|  | #include <array> | 
|  | #include <iterator> | 
|  | #include <string> | 
|  | #include <type_traits> | 
|  | #include <vector> | 
|  |  | 
|  | #include "base/containers/checked_iterators.h" | 
|  |  | 
|  | namespace gurl_base { | 
|  |  | 
|  | namespace internal { | 
|  |  | 
|  | template <typename T> | 
|  | struct PointsToObject : std::true_type {}; | 
|  | // std::iter_value_t is not defined for `T*` where T is not an object type. | 
|  | template <typename T> | 
|  | struct PointsToObject<T*> : std::is_object<T> {}; | 
|  |  | 
|  | // A pointer is a contiguous iterator. | 
|  | // Reference: https://wg21.link/iterator.traits#5 | 
|  | template <typename T> | 
|  | struct IsPointer : std::is_pointer<T> {}; | 
|  |  | 
|  | template <typename T, typename StringT = std::basic_string<iter_value_t<T>>> | 
|  | struct IsStringIterImpl | 
|  | : std::disjunction<std::is_same<T, typename StringT::const_iterator>, | 
|  | std::is_same<T, typename StringT::iterator>> {}; | 
|  |  | 
|  | // An iterator to std::basic_string is contiguous. | 
|  | // Reference: https://wg21.link/basic.string.general#2 | 
|  | // | 
|  | // Note: Requires indirection via `IsStringIterImpl` to avoid triggering a | 
|  | // `static_assert(is_trivial_v<value_type>)` inside libc++'s std::basic_string. | 
|  | template <typename T> | 
|  | struct IsStringIter | 
|  | : std::conjunction<std::is_trivial<iter_value_t<T>>, IsStringIterImpl<T>> { | 
|  | }; | 
|  |  | 
|  | // An iterator to std::array is contiguous. | 
|  | // Reference: https://wg21.link/array.overview#1 | 
|  | template <typename T, typename ArrayT = std::array<iter_value_t<T>, 1>> | 
|  | struct IsArrayIter | 
|  | : std::disjunction<std::is_same<T, typename ArrayT::const_iterator>, | 
|  | std::is_same<T, typename ArrayT::iterator>> {}; | 
|  |  | 
|  | // An iterator to a non-bool std::vector is contiguous. | 
|  | // Reference: https://wg21.link/vector.overview#2 | 
|  | template <typename T, typename VectorT = std::vector<iter_value_t<T>>> | 
|  | struct IsVectorIter | 
|  | : std::conjunction< | 
|  | std::negation<std::is_same<iter_value_t<T>, bool>>, | 
|  | std::disjunction<std::is_same<T, typename VectorT::const_iterator>, | 
|  | std::is_same<T, typename VectorT::iterator>>> {}; | 
|  |  | 
|  | // The result of passing a std::valarray to std::begin is a contiguous iterator. | 
|  | // Note: Since all common standard library implementations (i.e. libc++, | 
|  | // stdlibc++ and MSVC's STL) just use a pointer here, we perform a similar | 
|  | // optimization. The corresponding unittest still ensures that this is working | 
|  | // as intended. | 
|  | // Reference: https://wg21.link/valarray.range#1 | 
|  | template <typename T> | 
|  | struct IsValueArrayIter : std::is_pointer<T> {}; | 
|  |  | 
|  | // base's CheckedContiguousIterator is a contiguous iterator. | 
|  | template <typename T, typename ValueT = iter_value_t<T>> | 
|  | struct IsCheckedContiguousIter | 
|  | : std::disjunction< | 
|  | std::is_same<T, gurl_base::CheckedContiguousConstIterator<ValueT>>, | 
|  | std::is_same<T, gurl_base::CheckedContiguousIterator<ValueT>>> {}; | 
|  |  | 
|  | // Check that the iterator points to an actual object, and is one of the | 
|  | // iterator types mentioned above. | 
|  | template <typename T, bool B = PointsToObject<T>::value> | 
|  | struct IsContiguousIteratorImpl : std::false_type {}; | 
|  | template <typename T> | 
|  | struct IsContiguousIteratorImpl<T, true> | 
|  | : std::disjunction<IsPointer<T>, | 
|  | IsStringIter<T>, | 
|  | IsArrayIter<T>, | 
|  | IsVectorIter<T>, | 
|  | IsValueArrayIter<T>, | 
|  | IsCheckedContiguousIter<T>> {}; | 
|  |  | 
|  | }  // namespace internal | 
|  |  | 
|  | // IsContiguousIterator is a type trait that determines whether a given type is | 
|  | // a contiguous iterator. It is similar to C++20's contiguous_iterator concept, | 
|  | // but due to a lack of the corresponding contiguous_iterator_tag relies on | 
|  | // explicitly instantiating the type with iterators that are supposed to be | 
|  | // contiguous iterators. | 
|  | // References: | 
|  | // - https://wg21.link/iterator.concept.contiguous | 
|  | // - https://wg21.link/std.iterator.tags#lib:contiguous_iterator_tag | 
|  | // - https://wg21.link/n4284 | 
|  | template <typename T> | 
|  | struct IsContiguousIterator | 
|  | : internal::IsContiguousIteratorImpl<remove_cvref_t<T>> {}; | 
|  |  | 
|  | }  // namespace base | 
|  |  | 
|  | #endif  // BASE_CONTAINERS_CONTIGUOUS_ITERATOR_H_ |