:github_url: https://github.com/pytorch/pytorch .. _program_listing_file_c10_util_ArrayRef.h: Program Listing for File ArrayRef.h =================================== |exhale_lsh| :ref:`Return to documentation for file ` (``c10/util/ArrayRef.h``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp //===--- ArrayRef.h - Array Reference Wrapper -------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // ATen: modified from llvm::ArrayRef. // removed llvm-specific functionality // removed some implicit const -> non-const conversions that rely on // complicated std::enable_if meta-programming // removed a bunch of slice variants for simplicity... #pragma once #include #include #include #include #include #include #include #include #include #include #include #include namespace c10 { template class ArrayRef final { public: using iterator = const T*; using const_iterator = const T*; using size_type = size_t; using value_type = T; using reverse_iterator = std::reverse_iterator; private: const T* Data; size_type Length; void debugCheckNullptrInvariant() { TORCH_INTERNAL_ASSERT_DEBUG_ONLY( Data != nullptr || Length == 0, "created ArrayRef with nullptr and non-zero length! std::optional relies on this being illegal"); } public: /* implicit */ constexpr ArrayRef() : Data(nullptr), Length(0) {} // TODO Make this explicit constexpr ArrayRef(const T& OneElt) : Data(&OneElt), Length(1) {} constexpr ArrayRef(const T* data, size_t length) : Data(data), Length(length) { debugCheckNullptrInvariant(); } constexpr ArrayRef(const T* begin, const T* end) : Data(begin), Length(end - begin) { debugCheckNullptrInvariant(); } template /* implicit */ ArrayRef(const SmallVectorTemplateCommon& Vec) : Data(Vec.data()), Length(Vec.size()) { debugCheckNullptrInvariant(); } template < typename Container, typename U = decltype(std::declval().data()), typename = std::enable_if_t< (std::is_same_v || std::is_same_v)>> /* implicit */ ArrayRef(const Container& container) : Data(container.data()), Length(container.size()) { debugCheckNullptrInvariant(); } // The enable_if stuff here makes sure that this isn't used for // std::vector, because ArrayRef can't work on a std::vector // bitfield. template /* implicit */ ArrayRef(const std::vector& Vec) : Data(Vec.data()), Length(Vec.size()) { static_assert( !std::is_same_v, "ArrayRef cannot be constructed from a std::vector bitfield."); } template /* implicit */ constexpr ArrayRef(const std::array& Arr) : Data(Arr.data()), Length(N) {} template // NOLINTNEXTLINE(*c-arrays*) /* implicit */ constexpr ArrayRef(const T (&Arr)[N]) : Data(Arr), Length(N) {} /* implicit */ constexpr ArrayRef(const std::initializer_list& Vec) : Data( std::begin(Vec) == std::end(Vec) ? static_cast(nullptr) : std::begin(Vec)), Length(Vec.size()) {} constexpr iterator begin() const { return Data; } constexpr iterator end() const { return Data + Length; } // These are actually the same as iterator, since ArrayRef only // gives you const iterators. constexpr const_iterator cbegin() const { return Data; } constexpr const_iterator cend() const { return Data + Length; } constexpr reverse_iterator rbegin() const { return reverse_iterator(end()); } constexpr reverse_iterator rend() const { return reverse_iterator(begin()); } constexpr bool allMatch(const std::function& pred) const { return std::all_of(cbegin(), cend(), pred); } constexpr bool empty() const { return Length == 0; } constexpr const T* data() const { return Data; } constexpr size_t size() const { return Length; } constexpr const T& front() const { TORCH_CHECK( !empty(), "ArrayRef: attempted to access front() of empty list"); return Data[0]; } constexpr const T& back() const { TORCH_CHECK(!empty(), "ArrayRef: attempted to access back() of empty list"); return Data[Length - 1]; } constexpr bool equals(ArrayRef RHS) const { return Length == RHS.Length && std::equal(begin(), end(), RHS.begin()); } constexpr ArrayRef slice(size_t N, size_t M) const { TORCH_CHECK( N + M <= size(), "ArrayRef: invalid slice, N = ", N, "; M = ", M, "; size = ", size()); return ArrayRef(data() + N, M); } constexpr ArrayRef slice(size_t N) const { TORCH_CHECK( N <= size(), "ArrayRef: invalid slice, N = ", N, "; size = ", size()); return slice(N, size() - N); } constexpr const T& operator[](size_t Index) const { return Data[Index]; } constexpr const T& at(size_t Index) const { TORCH_CHECK( Index < Length, "ArrayRef: invalid index Index = ", Index, "; Length = ", Length); return Data[Index]; } template std::enable_if_t, ArrayRef>& operator=( // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward) U&& Temporary) = delete; template std::enable_if_t, ArrayRef>& operator=( std::initializer_list) = delete; std::vector vec() const { return std::vector(Data, Data + Length); } }; template std::ostream& operator<<(std::ostream& out, ArrayRef list) { int i = 0; out << "["; for (const auto& e : list) { if (i++ > 0) out << ", "; out << e; } out << "]"; return out; } template ArrayRef makeArrayRef(const T& OneElt) { return OneElt; } template ArrayRef makeArrayRef(const T* data, size_t length) { return ArrayRef(data, length); } template ArrayRef makeArrayRef(const T* begin, const T* end) { return ArrayRef(begin, end); } template ArrayRef makeArrayRef(const SmallVectorImpl& Vec) { return Vec; } template ArrayRef makeArrayRef(const SmallVector& Vec) { return Vec; } template ArrayRef makeArrayRef(const std::vector& Vec) { return Vec; } template ArrayRef makeArrayRef(const std::array& Arr) { return Arr; } template ArrayRef makeArrayRef(const ArrayRef& Vec) { return Vec; } template ArrayRef& makeArrayRef(ArrayRef& Vec) { return Vec; } template // NOLINTNEXTLINE(*c-arrays*) ArrayRef makeArrayRef(const T (&Arr)[N]) { return ArrayRef(Arr); } // WARNING: Template instantiation will NOT be willing to do an implicit // conversions to get you to an c10::ArrayRef, which is why we need so // many overloads. template bool operator==(c10::ArrayRef a1, c10::ArrayRef a2) { return a1.equals(a2); } template bool operator!=(c10::ArrayRef a1, c10::ArrayRef a2) { return !a1.equals(a2); } template bool operator==(const std::vector& a1, c10::ArrayRef a2) { return c10::ArrayRef(a1).equals(a2); } template bool operator!=(const std::vector& a1, c10::ArrayRef a2) { return !c10::ArrayRef(a1).equals(a2); } template bool operator==(c10::ArrayRef a1, const std::vector& a2) { return a1.equals(c10::ArrayRef(a2)); } template bool operator!=(c10::ArrayRef a1, const std::vector& a2) { return !a1.equals(c10::ArrayRef(a2)); } using IntArrayRef = ArrayRef; // This alias is deprecated because it doesn't make ownership // semantics obvious. Use IntArrayRef instead! C10_DEFINE_DEPRECATED_USING(IntList, ArrayRef) } // namespace c10