From 81f06865235c255fc309fdb30a83978a1e39fd58 Mon Sep 17 00:00:00 2001 From: Ben Clayton Date: Wed, 17 Aug 2022 15:42:15 +0000 Subject: [PATCH] tint/utils/vector: Allow use of incomplete types Attempting to make a Vector of an incomplete pointer type would trigger an error as the `CanReinterpretSlice` trail magic is wanting to know the base types, which isn't known yet. Split `CanReinterpretSlice` into class specializations, where the common case of no-cast doesn't look at the base types. Change-Id: Id016b027b131f7988ccf3cae93622dacb7802a1d Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/98140 Kokoro: Kokoro Reviewed-by: Dan Sinclair Commit-Queue: Ben Clayton --- src/tint/utils/vector.h | 55 +++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 10 deletions(-) diff --git a/src/tint/utils/vector.h b/src/tint/utils/vector.h index 518a69389d..b718840a5c 100644 --- a/src/tint/utils/vector.h +++ b/src/tint/utils/vector.h @@ -104,22 +104,42 @@ struct Slice { auto rend() const { return std::reverse_iterator(begin()); } }; +namespace detail { + +/// Private implementation of tint::utils::CanReinterpretSlice. +/// Specialized for the case of TO equal to FROM, which is the common case, and avoids inspection of +/// the base classes, which can be troublesome if the slice is of an incomplete type. +template +struct CanReinterpretSlice { + /// True if a slice of FROM can be reinterpreted as a slice of TO + static constexpr bool value = + // Both TO and FROM are pointers + (std::is_pointer_v && std::is_pointer_v)&& // + // const can only be applied, not removed + (std::is_const_v> || + !std::is_const_v>)&& // + // TO and FROM are both Castable + IsCastable, std::remove_pointer_t> && // + // FROM is of, or derives from TO + traits::IsTypeOrDerived, std::remove_pointer_t>; +}; + +/// Specialization of 'CanReinterpretSlice' for when TO and FROM are equal types. +template +struct CanReinterpretSlice { + /// Always `true` as TO and FROM are the same type. + static constexpr bool value = true; +}; + +} // namespace detail + /// Evaluates whether a `vector` and be reinterpreted as a `vector`. /// Vectors can be reinterpreted if both `FROM` and `TO` are pointers to a type that derives from /// CastableBase, and the pointee type of `TO` is of the same type as, or is an ancestor of the /// pointee type of `FROM`. Vectors of non-`const` Castable pointers can be converted to a vector of /// `const` Castable pointers. template -static constexpr bool CanReinterpretSlice = - // TO and FROM are both pointer types - std::is_pointer_v && std::is_pointer_v && // - // const can only be applied, not removed - (std::is_const_v> || - !std::is_const_v>)&& // - // TO and FROM are both Castable - IsCastable, std::remove_pointer_t> && - // FROM is of, or derives from TO - traits::IsTypeOrDerived, std::remove_pointer_t>; +static constexpr bool CanReinterpretSlice = detail::CanReinterpretSlice::value; /// Reinterprets `const Slice*` as `const Slice*` /// @param slice a pointer to the slice to reinterpret @@ -440,6 +460,21 @@ class Vector { /// @returns the end for a reverse iterator auto rend() const { return impl_.slice.rend(); } + /// Equality operator + /// @param other the other vector + /// @returns true if this vector is the same length as `other`, and all elements are equal. + bool operator==(const Vector& other) const { + const size_t len = Length(); + if (len == other.Length()) { + for (size_t i = 0; i < len; i++) { + if ((*this)[i] != other[i]) { + return false; + } + } + } + return true; + } + private: /// Friend class (differing specializations of this class) template